在Ruby中,如何编写一个简单的方法,可以与&:symbol一起使用?
In Ruby, how do you write a simple method that can be used with &:symbol?
这篇 article 触及了问题,但没有给出解决方案。
这开始于我想编写一个方法并有选择地向它传递一个可以为 null 或 ????
的参数(proc
、lambda
、method
、 block
, ???).我们暂时称它为 block
,因为 block
有效。 block
接受一个必需的参数。该方法及其调用的示例如下:
#!/usr/bin/env ruby
def foo(&proc)
puts "before"
if proc
yield "passed to proc"
end
puts "after"
end
def add_message(s)
puts "from add_message #{s}"
end
foo { |s| add_message(s) }
foo
输出为:
before
from add_message passed to proc
after
before
after
太棒了。但是,我想做的是能够像这样调用 foo
:foo(&:add_message)
。但我不能。更改上面的第 15 行我得到:
before
./temp.rb:11:in `add_message': wrong number of arguments (given 0, expected 1) (ArgumentError)
from ./temp.rb:6:in `foo'
from ./temp.rb:15:in `<main>'
而且,正如上面的文章提到的,现在的元数是 -2。那么,我该如何编写一个像 add_message
这样可以与 &:add_message
一起使用的简单方法呢?要么!!! 99.99% 的情况都是如此,请让我了解如何执行此操作的正确轨道。
class Integer
def set
return self + 1
end
end
p [1,2,3,4,5,6].map(&:set)
我认为当你可以使用 &:
语法时,已经为 class 定义了一个方法,就像上面的
问题是 Symbol#to_proc
没有创建正确调用 add_message
方法的过程。
# `yield` will pass it's arguments to proc
>> :add_message.to_proc.call('passed to proc')
# => ArgumentError
这会调用 'passed to proc'.add_message
,因为我们的方法是在 Object
中定义的,它在 String
上调用时有效,但是它缺少必需的参数。
解决方案是制作一个可以接受与 add_message
方法相同的参数并将它们传递给该方法的过程。我们可以使用 Object#method
那个 returns Method
对象,它实现了它自己的 to_proc
并且与方法具有相同的 arity。
>> method(:add_message).to_proc.arity
=> 1
>> method(:add_message).to_proc.call('passed to proc')
from add_message passed to proc
>> foo(&method(:add_message))
before
from add_message passed to proc
after
Conversion of other objects to procs
Any object that implements the to_proc
method can be converted into a proc by the &
operator, and therefore can be consumed by iterators.
class Greeter
def initialize(greeting)
@greeting = greeting
end
def to_proc
proc {|name| "#{@greeting}, #{name}!" }
end
end
hi = Greeter.new("Hi")
hey = Greeter.new("Hey")
["Bob", "Jane"].map(&hi) #=> ["Hi, Bob!", "Hi, Jane!"]
["Bob", "Jane"].map(&hey) #=> ["Hey, Bob!", "Hey, Jane!"]
Of the Ruby core classes, this method is implemented by Symbol
, Method
, and Hash
.
因此,当您传递一个前面带有一元符号的参数时,to_proc
会被调用。 &:
“语法”实际上是 &
在符号文字上调用,即 &(:foobar)
,并且 Symbol.to_proc
具有将符号转换为方法调用的行为参数,即这两个大致等价(模命名参数转发)
:foobar.to_proc
proc { |x, *args| x.foobar(*args) }
Ruby 的 Method
类型也实现了 to_proc
,所以如果你有一个名为 foobar
的独立方法(在模块上,比如说,Example
), 然后你可以调用 Example.method(:foobar)
并得到一个 &
兼容的对象。如果你有一个“top-level”方法,那么它可能是 并且在没有显式接收者的情况下调用 method
将起作用。
该引用中提到的另一种类型是散列,它可以变成一个函数,将它们的键映射到它们的值(如果不存在匹配的键,则返回 nil
)。当然,您始终可以自己实现一个名为 to_proc
的方法 类,它的工作方式与任何 built-in 类型一样好。
这篇 article 触及了问题,但没有给出解决方案。
这开始于我想编写一个方法并有选择地向它传递一个可以为 null 或 ????
的参数(proc
、lambda
、method
、 block
, ???).我们暂时称它为 block
,因为 block
有效。 block
接受一个必需的参数。该方法及其调用的示例如下:
#!/usr/bin/env ruby
def foo(&proc)
puts "before"
if proc
yield "passed to proc"
end
puts "after"
end
def add_message(s)
puts "from add_message #{s}"
end
foo { |s| add_message(s) }
foo
输出为:
before
from add_message passed to proc
after
before
after
太棒了。但是,我想做的是能够像这样调用 foo
:foo(&:add_message)
。但我不能。更改上面的第 15 行我得到:
before
./temp.rb:11:in `add_message': wrong number of arguments (given 0, expected 1) (ArgumentError)
from ./temp.rb:6:in `foo'
from ./temp.rb:15:in `<main>'
而且,正如上面的文章提到的,现在的元数是 -2。那么,我该如何编写一个像 add_message
这样可以与 &:add_message
一起使用的简单方法呢?要么!!! 99.99% 的情况都是如此,请让我了解如何执行此操作的正确轨道。
class Integer
def set
return self + 1
end
end
p [1,2,3,4,5,6].map(&:set)
我认为当你可以使用 &:
语法时,已经为 class 定义了一个方法,就像上面的
问题是 Symbol#to_proc
没有创建正确调用 add_message
方法的过程。
# `yield` will pass it's arguments to proc
>> :add_message.to_proc.call('passed to proc')
# => ArgumentError
这会调用 'passed to proc'.add_message
,因为我们的方法是在 Object
中定义的,它在 String
上调用时有效,但是它缺少必需的参数。
解决方案是制作一个可以接受与 add_message
方法相同的参数并将它们传递给该方法的过程。我们可以使用 Object#method
那个 returns Method
对象,它实现了它自己的 to_proc
并且与方法具有相同的 arity。
>> method(:add_message).to_proc.arity
=> 1
>> method(:add_message).to_proc.call('passed to proc')
from add_message passed to proc
>> foo(&method(:add_message))
before
from add_message passed to proc
after
Conversion of other objects to procs
Any object that implements the
to_proc
method can be converted into a proc by the&
operator, and therefore can be consumed by iterators.class Greeter def initialize(greeting) @greeting = greeting end def to_proc proc {|name| "#{@greeting}, #{name}!" } end end hi = Greeter.new("Hi") hey = Greeter.new("Hey") ["Bob", "Jane"].map(&hi) #=> ["Hi, Bob!", "Hi, Jane!"] ["Bob", "Jane"].map(&hey) #=> ["Hey, Bob!", "Hey, Jane!"]
Of the Ruby core classes, this method is implemented by
Symbol
,Method
, andHash
.
因此,当您传递一个前面带有一元符号的参数时,to_proc
会被调用。 &:
“语法”实际上是 &
在符号文字上调用,即 &(:foobar)
,并且 Symbol.to_proc
具有将符号转换为方法调用的行为参数,即这两个大致等价(模命名参数转发)
:foobar.to_proc
proc { |x, *args| x.foobar(*args) }
Ruby 的 Method
类型也实现了 to_proc
,所以如果你有一个名为 foobar
的独立方法(在模块上,比如说,Example
), 然后你可以调用 Example.method(:foobar)
并得到一个 &
兼容的对象。如果你有一个“top-level”方法,那么它可能是 method
将起作用。
该引用中提到的另一种类型是散列,它可以变成一个函数,将它们的键映射到它们的值(如果不存在匹配的键,则返回 nil
)。当然,您始终可以自己实现一个名为 to_proc
的方法 类,它的工作方式与任何 built-in 类型一样好。