Ruby Proc语法

我昨天提出的一个问题的答案是下面这段Ruby代码:

def overlap?(r1,r2) r1.include?(r2.begin) || r2.include?(r1.begin) end def any_overlap?(ranges) ranges.sort_by(&:begin).each_cons(2).any? do |r1,r2| overlap?(r1, r2) end end 

我得到each_cons ,但奇怪的是&:begin符号? 救我从句法地狱!

谢谢!

当你用&一个呼叫的最后一个参数前缀时&你清楚地表明你正在发送一个数据块,而不是一个正常的参数。 好的,在method(&:something):something是一个符号,而不是proc ,所以Ruby会自动调用to_proc方法来得到一个真正的块。 Rails家伙(现在也是Ruby)巧妙地将其定义为:

 class Symbol def to_proc proc { |obj, *args| obj.send(self, *args) } end end 

这就是为什么你可以这样做:

 >> [1, 2, 3].map(&:to_s) # instead of [1, 2, 3].map { |n| n.to_s } => ["1", "2", "3"] 

注意:当你意识到这个构造不是syntically sugar,而是Ruby提供的通用基础设施时,没有什么能阻止你为其他类实现你自己的to_proc 。 从来没有觉得有限,因为&:method不允许任何参数

 class Array def to_proc proc { |obj, *args| obj.send(*(self + args)) } end end >> ["1", "F", "FF"].map(&[:to_i, 16]) => [1, 15, 255] 

它等于:

 ranges.sort_by{|r| r.begin} 

my_method(&some_value)意味着调用my_method ,在特殊参数槽中传递some_value ,proc槽通常保留用于传递do-notation块。

 my_block = lambda { puts "hello" } (1..3).each(&my_block) 

任何Proc对象或响应to_proc被允许在proc-slot中传递。 如果你传递了一个不是Proc的对象,而是响应to_proc ,那么Ruby将会为你调用to_proc对象,并将结果传递给方法。

Symbol#to_proc的实现是返回一个proc,当传递一个参数的时候,这个proc就会发送这个参数,这个消息就是这个符号本身。 例如, :hello.to_proc.call(my_obj)最终会做my_obj.send :hello

因此, my_array.each(&:hello)会传入:helloeach proc-slot(如果你使用do-notation来创build一个块,通常会通过一个块)。 :hello.to_proc.call(my_array[0])最终是my_array[0].send :hello ,对于my_array所有后续索引都是一样的。