【问题标题】:Behaviour of Array bang methodsArray bang 方法的行为
【发布时间】:2010-09-18 13:39:14
【问题描述】:

Array 方法的某些 bang 版本类似于 compact!reject!flatten!uniq! 如果没有进行任何更改,则返回 nil

[1,[2]].flatten!
# => [1, 2]
[1,2].flatten!
# => nil
[1,[2]].flatten
# => [1, 2]
[1,2].flatten
# => [1, 2]

[1,2,nil].compact!
# => [1, 2]
[1,2].compact!
# => nil
[1,2,nil].compact
# => [1, 2]
[1,2].compact
# => [1, 2]

如果他们这样做,那肯定是有原因的。有什么想法吗?

【问题讨论】:

    标签: ruby arrays


    【解决方案1】:

    bang (!) 方法确实修改了当前对象,但如果每个the documentation 没有受影响的元素,它们确实返回nil。如果出于某种原因,如果您确实修改了有问题的数组,则需要执行某些操作,这很有用。

    if array.flatten!
      puts "Oh yeah... flattened that array!"
    end
    

    【讨论】:

    • 这是一个很好的观点。但是你不能说return array.flatten!,在我看来,这似乎也很有用
    • 是的。如果这是你想要的,你会说return array.flatten(没有爆炸声),它会返回一个原始数组的扁平副本。
    • 这迫使我在不需要的地方制作副本。这正是我在使用 banged 版本时遇到麻烦的原因。
    • 明白了。是的,你需要return array.flatten! || array(或将其分成两个语句),这不是非常优雅,IMO,但这是我目前能想到的唯一选择。
    • 这可能是一个尚未修复的设计缺陷,因为它会破坏代码。我想每个人都会同意返回对象本身比知道它是否改变更重要。 Array 类甚至不连贯:Array#sort!始终返回对象,即使没有进行任何更改。另一方面,Python 有一个不同的策略:就地操作返回 nil (None) 来强调它。最后:当您在就地操作后返回一个对象时,最安全和最清晰的可能是一个简单的:1)obj.operation! + 2) (返回) obj.
    【解决方案2】:

    我一直觉得 Array 方法的 bang 版本是 只是他们的方式不同 就地修改对象。

    也许这里的问题是,这个印象并不真正正确:according to David A. Black, ! 并不意味着该方法改变了它的接收者; ! 表示此方法是其他等效方法的“危险”版本,它具有相同的名称减去 !

    现在危险有多种形式(强调我的):

    有时你会得到不止一种 即使在一声巨响内也没有“危险” 方法。采取String#gsub!。这 方法改变了它的接收者:

    str = "David" 
    str.gsub!(/$/, " Black")
    str                        # David Black
    

    它也不同于gsub(非爆炸) 如果字符串没有改变, gsub 返回未更改的副本 字符串,但 gsub! 返回 nil:

    str.gsub(/xyz/, "blah")    # David Black
    str.gsub!(/xyz/, "blah")   # nil
    str                        # David Black
    

    !在gsub! 给你一个提示: 它警告你危险,这意味着 在你使用这个方法之前,你 应该弄清楚它到底是怎么回事 行为。(一个简单的“ri String#gsub!” 应该这样做。)

    这种“单挑”语义也适用于 Array 的 bang 方法。

    【讨论】:

    • 我也读过这篇文章——这毫无意义。 “危险”的含义充其量被确定为反直觉行为的标志。好吧,也许他们一开始就不应该这样做?
    • before you use the method, you should find out exactly how it behaves 显然不是红宝石方式,通常整个约定生态系统自然会导致正确的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    相关资源
    最近更新 更多