Ruby 为什么Symbol#to_proc会有这种行为?

Ruby 为什么Symbol#to_proc会有这种行为?,ruby,Ruby,我发现这个示例代码在Ruby中实现了自定义符号#to_proc: class Symbol def to_proc puts "In the new Symbol#to_proc!" Proc.new { |obj| obj.send(self) } end end 它包括额外的“puts…”字符串,以确保它不是内置方法。当我执行代码时 p %w{ david black }.map(&:capitalize) 结果是: In the new Symbol#t

我发现这个示例代码在Ruby中实现了自定义符号#to_proc:

class Symbol
  def to_proc
    puts "In the new Symbol#to_proc!"
    Proc.new { |obj| obj.send(self) }
  end
end
它包括额外的“puts…”字符串,以确保它不是内置方法。当我执行代码时

p %w{ david black }.map(&:capitalize)
结果是:

In the new Symbol#to_proc!
["David", "Black"]
但为什么不是这样呢

In the new Symbol#to_proc!
["David"]
In the new Symbol#to_proc!
["Black"]

我的逻辑是这样的:映射产生一个接一个的元素来块。块获取第一个元素并执行.to_proc,而不是第二个。但是为什么puts只执行一次?

调用
to_proc
方法一次,返回一个proc对象,然后重复使用,因此您看到了正确的行为

如果您将puts移动到内部,您将看到您所期望的:

class Symbol
  def to_proc
    Proc.new { |obj|
      puts "In the new Symbol#to_proc!"
      obj.send(self)
    }
  end
end

在Ruby中,map使用块。
&
操作符调用它后面的对象上的
到_proc
,并将调用
到_proc
返回的值作为一个
进行映射。有了这些信息,让我们再看看您的示例。在您的示例中,
&:capitalize
将导致调用
以调用
:capitalize
上的\u proc
方法。由于,
:capitalize
是一个符号,它将调用
来处理符号类上的
,由您重新定义

:capitalize.to_proc
将返回:

In the new Symbol#to_proc!
=> #<Proc:0x007fa08183df28@(irb):4>
在新符号中#to_proc!
=> #
&
操作符将使用返回的Proc对象,并将该Proc对象作为块传递给map。在重新定义的
to_proc
方法定义中,
put
刚刚开始执行,由于
put
打印到控制台(假设您在控制台中运行),您将看到它被打印。它从来没有传递给地图,所以你永远不会看到它打印两次


然而,如果你想要你期望的行为,使用第一个答案。希望能有帮助。

@bjhaid:这不是重复的答案。“没问题。@bjhaid:嗯,是的,我不同意你的观点。谢谢你的解释,但我不明白为什么Proc对象只创建一次。为什么不为每个映射块调用创建新的Proc对象?我确信Ruby能够正确地执行代码,但我找不到一个很好的解释来解释这种情况。为什么您希望每个循环都有一个全新的过程?这将是非常浪费的,因为
map
和类似函数的整个思想是将完全相同的函数应用于许多对象。如果要对每个元素应用不同的函数,则应使用
each
,其中包含一个自定义代码位。这给了你最大的灵活性。这是一个完美的答案,现在我明白发生了什么。谢谢