何时使用(:方法)或(&:方法)

时间:2015-06-15 22:59:40

标签: ruby

为什么:respond_to?在:

class Wolf
  def howl; end
end

Wolf.new.respond_to?(:howl) # => true
&中,

不需要map

["1", "2", "3"].map(&:to_i) # => [1, 2, 3]

呢?另外,有没有技术名称?

1 个答案:

答案 0 :(得分:2)

当你说:method时,你在ruby中使用一些很好的语法糖来创建一个新的Symbol对象。当你在它之前抛出一个&符号(&:method)时,你正在使用另一块糖。这会在符号上调用to_proc方法。

所以,这两件事是相同的:

method_proc = &:method

sym = :method
method_proc = method.to_proc

它与其他用法之间的区别是什么?好吧,respond_to?有一个参数 - 一个符号。所以我们可以通过:method并且一切都很好和花花公子。 (有趣的是,对象确实响应了名为method的方法,但这是一个更令人困惑的问题。)

相比之下,可枚举的迭代器(如mapselect等)接受一个块。当我们传递Proc时,它被正确解释为该块。所以,这两段代码是等价的:

[1,2,3].map { |i| i.even? }
[1,2,3].map(&:even?)

这种等同性有点令人困惑,因为当然Symbol并不知道某处有even?方法。为了解决它,我使用evenproc = :even?.to_proc来检查结果proc。它在C中实现(至少在MRI ruby​​中),并且不愿意放弃它的来源。但是,其arity-1,这意味着它接受一个可选的arg。我最好的猜测是它做了这样的事情:

def to_proc
  method_name = self.to_s
  ->(a) { a.send(method_name) }
end

我可以进一步挖掘,但我认为我们已经超越了这个问题。 ;)祝你好运!