我遇到了代码库中的node_modules
,我不知道发生了什么。这发生在&method
:
irb
这里发生了什么?
我熟悉&等于[12,3].map(&method(:to_s))
#=> ArgumentError: wrong number of arguments (given 1, expected 0)
["12","3"].map(&method(:Integer))
#=> [12, 3]
,但我仍然无法在这里连接点。
答案 0 :(得分:5)
在&method(:to_s)
中,.to_s
取自当前上下文(顶级对象main
)。此版本已绑定到接收方,不接受进一步的参数。但是.map
(数组的每个元素)都会传递一个参数,这就是它的作用。
看看这个正在发生的事情的逐步重建
to_s # => "main"
method(:to_s) # => #<Method: main.to_s>
method(:to_s).to_proc # => #<Proc:0x007ff73a27e1e0 (lambda)>
method(:to_s).to_proc.call(12) # =>
# ~> -:6:in `to_s': wrong number of arguments (given 1, expected 0) (ArgumentError)
# ~> from -:6:in `<main>'
现在比较如果是.map(&:to_s)
:to_s.to_proc.call(12) # => "12"
我遇到了代码库中的
&method
在这种情况下它可能很有用:对每个元素应用一段逻辑,但这个逻辑来自当前上下文,完全在元素外部。看看这个人为的例子:
class Tweet
attr_accessor :text
def initialize(text)
@text = text
end
def shortened_links
find_links.map(&method(:shorten_link))
# same as
# find_links.map {|link| shorten_link(link) }
end
private
def find_links
# detect links in text
end
def shorten_link(url)
# use bit.ly or whatever
end
end
此处links
是字符串的集合。他们肯定不能缩短自己。
答案 1 :(得分:1)
以下是您的代码,其中&
字面替换为适当的块:
[12,3].map { |v| to_s(v) }
["12","3"].map { |v| Integer(v) }
在控制台中调用时,to_s
和Integer
是Object
类中的方法。 (技术上Integer()
来自Kernel
,包含在对象中。
to_s
definition没有参数,这就是您获得ArgumentError
的原因。
Integer
method可以接受1个或2个参数。
答案 2 :(得分:0)
method()
是Ruby中将常规方法转换为可传递对象的一种方法。它返回方法类型的对象。假设在method()
调用前面有一个&,返回的Method对象将收到一条#to_proc消息。
Method#to_proc返回一个lambda,它将接收到的参数传递给对原始方法的调用。
class Method
def to_proc
lambda { |*args| self.call(*args) }
end
end
这是#to_s情况的简化视图:
[1, 2, 3].map { |n| to_s.call(n) } # ArgumentError