使用do ... end blocks时,map,select等的行为不同

时间:2016-01-06 18:40:48

标签: ruby

当我使用#top_bar .phone .icon-phone:after { content: 'Foo:'; } #top_bar .phone:last-child .icon-phone:after { content: 'Bar:'; }<div id="top_bar"> <ul class="contact_details"> <li class="phone"> <i class="icon-phone"></i><a href="tel:00001">00001</a> </li> <li class="phone"> <i class="icon-phone"></i><a href="tel:00002">00002</a> </li> <li class="mail"> <i class="icon-mail "></i><a href="mailto:foo@bar.com ">foo@bar.com</a> </li> </ul> </div>和其他Enumerable方法时,我注意到以下行为上的差异。

我们假设我们有如下的哈希:

map

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

h = {a: 1}

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

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

知道为什么这种行为的差异?我经常遇到这个问题,因为我在工作时继续使用inspect Enumerator,这种行为经常破坏我的思考过程。

3 个答案:

答案 0 :(得分:4)

运营商优先事项。

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,在没有块的情况下调用,返回一个枚举器。

答案 1 :(得分:2)

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

执行此操作时:

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

......你实际上是这样做的:

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

换句话说,您将h.select(没有参数,返回枚举数)的结果作为参数传递给p,并且您还将块参数传递给{{ 1}}。 p显然默默地忽略了阻塞论点。

相反,当你这样做时:

p

......你实际上是这样做的:

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

也就是说,您将p(h.select {|k, v| true }) 的结果传递给h.select { |k, v| true },这会为您提供您期望的结果。

如果你想使用p语法并获得你想要的结果,你必须将整个事物包装在括号中:

do...end

它不漂亮,但它有效。

答案 2 :(得分:0)

根据官方文件网站

  

返回一个新的哈希,该哈希由块返回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