如何使用`:rand`作为map/collect的一元方法?

ric*_*ici 1 ruby

我想要一个包含滚动10个骰子的结果的矢量(比方说).我可以做这个:

([6]*10).map{|x|rand(x)}
Run Code Online (Sandbox Code Playgroud)

但这给了我一个"错误的参数数量"错误:

([6]*10).map(:rand)
Run Code Online (Sandbox Code Playgroud)

有一个免费的点对点的方式来传递的一个参数版本randmap

Jör*_*tag 6

这将有效:

([6]*10).map(&method(:rand))
Run Code Online (Sandbox Code Playgroud)

这不会:

([6]*10).map(&:rand)
Run Code Online (Sandbox Code Playgroud)

Symbol#to_proc 是(大致)实现如下:

class Symbol
  def to_proc
    -> *args { args.first.public_send(self, *args.drop(1)) }
  end
end
Run Code Online (Sandbox Code Playgroud)

换句话说,它将第一个参数作为接收者,将其他参数作为由该命名的方法的参数Symbol.所以,在你的情况下,它正在呼唤

6.rand
Run Code Online (Sandbox Code Playgroud)

一遍又一遍.

这种"类型"的作用,因为6是一个Integer,Integer是一个间接的子类Object,混合在一起Kernel,定义rand.但!rand是的private,这意味着它只能在没有显式接收器的情况下调用.此外,你没有传递任何参数,因此即使它是public,你也会得到rand没有参数的行为,这是Float0到1之间的行为.

Method#to_proc传递方法的所有参数(毕竟它已经有接收器绑定),所以在这种情况下,它将调用

self.rand(6)
Run Code Online (Sandbox Code Playgroud)

一遍又一遍.这当然有效,因为self是一个Object,Object包括Kernel,并rand在其中定义Kernel.

这不会有效:

([6]*10).map(:rand)
Run Code Online (Sandbox Code Playgroud)

原因很简单,map没有任何参数,但是你传递了一个参数.