1

我昨天在这里提出的问题的答案是以下 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符号是什么?把我从语法地狱中拯救出来!

谢谢!

4

3 回答 3

7

当您在调用的最后一个参数前面加上前缀时,&您清楚地表明您正在发送一个块而不是普通参数。好的, inmethod(&:something):something一个符号,而不是proc,所以 Ruby 会自动调用该方法to_proc来获取一个真正的块。Rails 的人(现在还有 vanilla 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"]

[编辑] 注意:当你意识到这个构造不是语法糖而是 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]
于 2010-12-22T19:08:06.713 回答
2

my_method(&some_value)表示调用my_method,传入some_value特殊的参数槽,proc-slot,通常保留用于传递 do-notation 块。

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

任何作为 aProc或响应的对象to_proc都允许在 proc-slot 中传递。如果您传入一个不是 aProc但响应的对象to_proc,那么 Ruby 将为to_proc您调用该对象并将结果传递给该方法。

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

所以my_array.each(&:hello)传递:helloeachproc-slot (如果你使用 do-notation 来制作一个块,一个块通常会传递的地方)。:hello.to_proc.call(my_array[0])最终成为my_array[0].send :hello,并且对于 的所有后续索引都相同my_array

于 2010-12-22T19:11:09.513 回答
1

它等于:

ranges.sort_by{|r| r.begin}
于 2010-12-22T18:55:37.450 回答