&amp ;:带参数的方法的语法

时间:2017-09-17 08:56:55

标签: ruby

我有一个嵌套数组:

a = [[1, "Aldous Huxley"],
     [3, "Sinclair Lewis"],
     [2, "Ernest Hemingway"],
     [4,"Anthony Burgess"]]

a.collect { |author| author.drop(1) }

输出

[["Aldous Huxley"], ["Sinclair Lewis"], ["Ernest Hemingway"], ["Anthony Burgess"]]

,而

a.collect(&:drop(1))

给我一​​个sintax错误。

SyntaxError: (irb):18: syntax error, unexpected '(', expecting ')'
a.collect(&:drop(1))
                  ^

是否可以在&amp ;: syntax?

中定义原始块表达式

2 个答案:

答案 0 :(得分:6)

不,这是不可能的。

&语法是语法糖,字面意思如下:

  • 将参数转换为Proc个实例,并在其上调用to_proc;
  • 使用proc作为块,将枚举器中的参数传递给它。

(&:foo)有效,因为Symbol.to_proc存在。

(&:foo(arg))无法解析,因为:之后需要有效的符号字符,而左括号会引发语法错误。

答案 1 :(得分:6)

冒号是Ruby中Symbol的一部分,&是通过调用对象上的to_proc并将其用作块来实现该语法的神奇工具。因此,虽然您不能使用:drop(1)之类的符号,但您可以在不使用符号的情况下完成此操作:

1)从方法中返回一个proc并将其传递给:

def drop(count)
  proc { |instance| instance.drop(count) }
end
a.collect(&drop(1))

2)传入响应to_proc的对象:

class Drop
  def initialize(how_many = 1)
    @to_drop = how_many
  end

  def to_proc
    proc { |instance| instance.drop(@to_drop) } 
  end
end
drop = Drop.new(1)
a.collect(&drop) # or, more succinctly
a.collect(&Drop.new(1))

在这种简单的情况下,定义返回procs或响应to_proc的对象的方法可能有点过分,只是将块传递给collect更好,但可能会有一些用例不是。

更新:考虑到这一点,Symbol类没有call方法,但这并不意味着它不能:

module SymbolCall
  def call(*args)
    proc { |instance| instance.public_send(self, *args) }
  end
end

class Symbol
  include SymbolCall
end

a.collect(&:drop.(1)) # or
a.collect(&:drop.call(1))

请确保您不要忘记它实际上是一种方法调用:drop.(1) 而不是 :drop(1)