为什么 Ruby 只允许在调用 to_proc 时通过符号引用方法?

Why does Ruby only allow to refer to methods by symbols when calling to_proc on them?

这个有效:

strings = ["1", "2", "3"]
nums = strings.map(&:to_i)

我们看到应用于 Symbol 对象的 & (to_proc 方法) 变成了一个块。 但是,这不起作用:

strings = ["1", "2", "3"]
nums = strings.map(&to_i)
nums = strings.map("to_i".to_sym.to_proc) #...neither does this

为什么不起作用?没有其他方法可以编写上面的代码吗?我很困惑,因为有两种方法可以访问 class:

的方法
"1".method(:to_i).call #works as well as
"1".method("to_i").call 

因此可以通过符号或字符串访问方法的名称。

nums = strings.map(&to_i)

不起作用,因为 to_i 未在主环境中定义。

nums = strings.map("to_i".to_sym.to_proc)

不起作用,因为 Proc 实例不是块。块甚至不是对象。

你可以写:

nums = strings.map(&"to_i".to_sym)

给定以下有效 Ruby 示例:

"to_i".to_sym.to_proc.call("1")

要在 Symbol 上调用 #to_proc 会创建一个接收一个参数的 proc:应该接收对由该符号命名的方法的调用的对象。像这样:

->(object) {
  object.send(:to_i)
}

& 所做的是将 #to_proc 返回的块作为适当的调用块传递给被调用的方法。与Enumerable#map一起使用时,最后的结果是传递的 将为集合中的每个元素调用块并接收 当前迭代元素作为参数传递给块。

所以 ["1", "2"].map(&:to_i) 语法是类似于 这个:

block = ->(el) {
  el.send(:to_i)
}

["1", "2"].map &block

关于你的例子:

当您尝试在示例中调用 &to_i 时,Ruby 将尝试调用 名为 to_i 的变量或方法。因为它不存在于 作用域(它是 Array 中每个 String 的方法,而不是 "global" 作用域中的方法),它会产生一个错误。

关于另一个示例:"to_i".to_sym.to_proc 将转换 :to_i 进入一个过程,当用一个参数调用时,将尝试 针对目标调用以符号 (:to_i) 命名的方法 范围。这意味着您可以使用 & 来转换过程 变成 "invocation block":

["1", "2"].map(&"to_i".to_sym.to_proc)