所以我试图弄清楚sym.to_proc方法的工作方式,据推测,任何实现to_proc的对象都有一个简写,该简写只是对象前的&,但是这种简写的行为似乎很不稳定:

这有效

irb(main):022:0> p = :to_s.to_proc
=> #<Proc:0x00000000056c33b0(&:to_s)>

但这不是
irb(main):023:0> p = &:to_s
Traceback (most recent call last):
    3: from X:/Ruby26-x64/bin/irb.cmd:31:in `<main>'
    2: from X:/Ruby26-x64/bin/irb.cmd:31:in `load'
    1: from X:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
SyntaxError ((irb):23: syntax error, unexpected &)
p = &:to_s
    ^

现在反过来,这可行
irb(main):024:0> (0..10).map &:to_s
=> ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]

但这不是!
irb(main):025:0> (0..10).map(:to_s.to_proc)
Traceback (most recent call last):
    5: from X:/Ruby26-x64/bin/irb.cmd:31:in `<main>'
    4: from X:/Ruby26-x64/bin/irb.cmd:31:in `load'
    3: from X:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
    2: from (irb):25
    1: from (irb):25:in `map'
ArgumentError (wrong number of arguments (given 1, expected 0))

这些错误似乎没有任何意义,我真的很茫然。

最佳答案

&一元前缀“&”运算符/符号可以在两个地方使用:

  • 在参数列表中。
  • 在参数列表中。

  • 在参数列表中,&一元前缀“&”符号表示“将作为参数传递的块作为参数,将其汇总到Proc对象中,并将其绑定(bind)到此参数。”

    在参数列表中,&一元前缀“&”运算符的意思是“将作为参数传递的Proc对象,展开为一个块,然后将其作为块参数传递。”更精确地讲,这就是启用像Symbol#to_proc这样的“技巧”的原因,它的意思是“接受作为参数传递的Proc对象,或者如果它还不是to_proc,则使用Proc转换该对象,将其展开为一个块,然后将其传递作为一个整体参数。”

    从某种意义上说,两者正好相反。

    在第一个示例的第二种情况下,您既没有参数列表也没有参数列表,因此&一元前缀&符号和&一元前缀&符号运算符在语法上均不合法。

    在第二个示例的第二种情况下,您将:to_s.to_proc的结果作为Proc的参数传递,该结果是Range#map对象。但是,Range#map没有任何参数(除了每个方法在Ruby中都具有的隐式块参数之外),因此您要传递一个参数,该参数不希望有任何参数。您必须将Proc参数展开为如下所示的块:

    (0..10).map(&(:to_s.to_proc))
    

    可以缩短为

    (0..10).map(&:to_s)
    

    因为如果操作数还不是&对象,则Proc一元前缀“&”运算符将自行执行转换。

    09-07 11:26