Ruby&方法表示法。到底是怎么回事?

时间:2017-03-28 15:33:21

标签: ruby

我遇到了代码库中的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] ,但我仍然无法在这里连接点。

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_sIntegerObject类中的方法。 (技术上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