为什么 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)
这个有效:
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)