rici rici - 7 months ago 23
Ruby Question

How do I use `:rand` as a unary method with map/collect?

I want a vector containing the result of rolling 10 dice (say). I can do this:


But this gives me a "wrong number of arguments" error:


Is there a point-free way to pass the one-argument version of


This will work:


This won't:


Symbol#to_proc is (roughly) implemented like this:

class Symbol
  def to_proc
    -> *args { args.first.public_send(self, *args.drop(1)) }

In other words, it takes the first argument as the receiver and the other arguments as arguments to the method that is named by the Symbol. So, in your case, it is calling


over and over.

This "kind of" works, because 6 is an Integer, Integer is an indirect subclass of Object, which mixes in Kernel, which defines rand. But! rand is private, which means it can only be called without an explicit receiver. Also, you aren't passing any arguments, therefore even if it were public, you'd get the behavior of rand without arguments, which is a Float between 0 and 1.

Whereas Method#to_proc passes all arguments to the method (it already has its receiver bound, after all), so in this case, it will call


over and over. Which of course works, because self is an Object, Object includes Kernel, and rand is defined in Kernel.

This won't work as well:


For the simple reason that map doesn't have any parameters, but you are passing an argument.