为什么我有时需要在 proc 作为 arg 传递时使用 & 作为前缀?

Why do I sometimes need to prefix proc with & when passing it as an arg?

我正在学习 Ruby 并被告知,引用 Codecademy:

When passing a proc to a method, an & is used to convert the proc into a block.

因此以下作品:

cube = Proc.new do |num| num ** 3 end
puts [1, 2, 3].map!(&cube) #errors without &

但是如果我将 proc 传递给用户定义的函数,它只在 没有 & 和错误 with它。

foo = Proc.new do puts 'foo' end
def bar(cb)
  cb.call
end
bar(foo) #bar(&foo) results in error

那么我应该如何理解整个有-&和没有-&的区别呢?它与内置方法(map(),在我的例子中)和用户定义的方法有关吗?

If I pass a proc to a user-defined function, it works only without the & and errors with it.

那是因为在您的示例中 cb 是位置参数。要将其声明为 block argument,您需要在其前面加上 &:

def bar(&cb)
  cb.call
end

foo = Proc.new { puts 'foo' }
bar(&foo) 

或者简单地说:

def bar
  yield
end

foo = Proc.new { puts 'foo' }
bar(&foo)

拥有实际的块参数还允许您跳过 proc 创建并将其称为:

bar { puts 'foo' }

# or

bar do
  puts 'foo'
end

So how should I understand the whole with-& and without-& difference?

Ruby中有3种方法参数:

  • 位置参数,例如foo(1, 2, 3)
  • 关键字参数,例如foo(a: 1, b: 2, c: 3)
  • 块参数,例如foo { puts "hello" }

由于 proc 是对象,您可以将它们作为位置参数或关键字参数传递,就像任何其他对象一样。

但是如果你想让一个proc成为一个块参数,你需要&来转换它。