【问题标题】:Different behavior with map, select, etc. when using do...end blocks [duplicate]使用 do...end 块时,map、select 等的不同行为 [重复]
【发布时间】:2016-04-10 23:17:49
【问题描述】:

当我使用 mapselect 和其他 Enumerable 方法时,我注意到以下行为差异。

假设我们有一个如下所示的哈希:

h = {a: 1}

以下代码按预期打印select 的输出。

p h.select { |k, v| true }
#=> {:a=>1}

但是,下面的代码显示输出是Enumerator,即使提供了一个块。

p h.select do |k, v| 
  true 
end
#=> #<Enumerator: {:a=>1}:select>

知道为什么会有这种行为差异吗?我经常遇到这个问题,因为我在工作时一直使用inspect p,这种行为经常使我的思维过程脱轨。

【问题讨论】:

    标签: ruby


    【解决方案1】:

    运算符优先级很重要。

    p h.select do |k, v| true end
    

    实际上是这样执行的:

    (p h.select) do |k, v| true end
    

    同时

    p h.select { |k, v| true }
    

    被视为:

    p (h.select { |k, v| true })
    

    Enumerable#select,在没有块的情况下调用,返回一个枚举器。

    【讨论】:

    • 有什么出路,我需要在它周围加上括号来解决优先级。
    • 这完全取决于你。而且,是的,括号会起作用。
    • 它可能不是运算符优先级,可能是函数调用参数的解释方式。评估是否更有可能以p(h.inspect) do..end 而不是(p h.select) do ...end 进行?
    【解决方案2】:

    我认为@mudasobwa 的回答基本上是正确的,但我想澄清关于优先级的实际情况。

    当你这样做时:

    p h.select do |k, v| 
      true 
    end
    

    ...您实际上正在这样做:

    p(h.select) do |k, v| 
      true 
    end
    

    换句话说,您将h.select 的结果(没有参数,它返回一个枚举器)作为参数传递给p,并且您还将一个块参数传递给pp 显然默默地忽略了 block 参数。

    相反,当你这样做时:

    p h.select {|k, v| true }
    

    ...您实际上正在这样做:

    p(h.select {|k, v| true })
    

    也就是说,您将h.select { |k, v| true } 的结果传递给p,从而得到您期望的结果。

    如果你想使用do...end 语法并得到你想要的结果,你必须把整个东西用括号括起来:

    p(h.select do |k, v| 
      true 
    end)
    

    它不漂亮,但它有效。

    【讨论】:

    • 知道为什么do...end{...} 都不会被视为p 的块,如您的答案的第一种情况所示
    • 别担心,我从另一个SO thread得到了答案。
    • 我无法解释它,只能说解析器是这样工作的。可能有一些技术原因,但我怀疑这只是一个设计选择。每种风格都有一个很好的用例,但不幸的是,它有时会让人们措手不及。
    【解决方案3】:

    根据官方文档网站

    返回一个新的哈希,该哈希由块返回 true 的条目组成。

    如果没有给出块,则返回一个枚举器。

    这是C语言中方法的代码

    rb_hash_select(VALUE hash)
    {
        VALUE result;
    
        RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
        result = rb_hash_new();
        if (!RHASH_EMPTY_P(hash)) {
            rb_hash_foreach(hash, select_i, result);
        }
        return result;
    }
    

    http://ruby-doc.org/core-2.3.0/Hash.html#method-i-select

    【讨论】:

    • 我提供了一个块,它仍然返回一个枚举器
    • 那应该不是select方法吧?而是与 p 方法有关?
    • 从其他答案看来是这样的
    猜你喜欢
    • 2020-10-21
    • 2021-09-22
    • 2014-01-29
    • 2014-07-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多