2

I was looking that in Ruby there are a lot of ways to declare arrays objects like:

[1,2,3]
Array.new(3){|i| i+1}

Even with more trickier ways like:

Array.new(3, &1.method(:+))

Where the &1.method(:+) means that the object 1 (reference by value) is responding to the method + directly referenced, so every time (3 times in this case) the array is executing the block, the object increments by 1. I would appreciate any correction if I'm wrong on my analysis here.

So, passing that, there is this case that I'm not completely following:

Array.new(3, &:next)

The question is:

What's the & doing in this case? I can guess that is a reference to some value directly but I don't know which one exactly. And after the &, how the :next is acting in this case.

Beforehand, I really appreciate your help. I'm getting the grasp of Ruby and I'm liking it even more!

Azeem
  • 11,148
  • 4
  • 27
  • 40
jcamejo
  • 95
  • 9
  • @Salil It's not a duplicate of that question. At the time, that was a Rails hack. Nowadays, it is a Ruby feature. – sawa Dec 07 '17 at 13:00
  • 1
    `&1` does not mean "1 referenced by value". – Stefan Dec 07 '17 at 14:02
  • @Stefan thanks for pointing out but what does it mean? I'm doing my research and is an operator that converts the whole expression 1.method(:+) (a non Proc object) into a Proc object. something that can be expected for the array constructor. Am i correct? – jcamejo Dec 07 '17 at 15:11
  • 2
    `&` turns a proc or lambda into a block argument. If the given object is not a proc or lambda, it will try to convert it via `to_proc`. In your example, `1.method(:+)` returns an instance of `Method`, so `&` will call its `to_proc` method and pass the resulting proc as a block argument to `Array.new`. – Stefan Dec 07 '17 at 15:25

1 Answers1

0

& is a shortcut for Symbol#to_proc in this case. A corresponding full version is:

Array.new(3) { |i| i.next }
#=> [1, 2, 3]

The instance below can help you understanding how does it work:

Array.new(3, &(:next.to_proc))
#=> [1, 2, 3]
Ilya
  • 13,337
  • 5
  • 37
  • 53
  • Thanks! The second case works because if i put the & in front of an instance that is not a proc, it will look for a to_proc method in that class. Am i correct? – jcamejo Dec 07 '17 at 12:53
  • 5
    Just to be clear: If all `&` did was to call `.to_proc` (which "`&` is a shortcut for `Symbol#to_proc`" certainly implies), `Array.new(3, :next.to_proc)` should work. But it doesn't because `Array.new` wants a block, not a `Proc`, so you need the `&` to convert to a block. – sepp2k Dec 07 '17 at 13:06
  • Sorry i need another clarification on this, the second argument on the array constructor it corresponds to a "default object" so what i understand this works because the "default object" is only created once right? – jcamejo Dec 07 '17 at 13:08
  • @jcamejo We're not invoking the 2-argument version of `Array.new`, we're invoking the version that takes one argument and a block. And that one invokes the block each time. – sepp2k Dec 07 '17 at 13:41