To populate an array I could write [*2..10]
, which gives [2, 3, 4, 5, 6, 7, 8, 9, 10]
.
How does this work?
To populate an array I could write [*2..10]
, which gives [2, 3, 4, 5, 6, 7, 8, 9, 10]
.
How does this work?
The expression 2..10
uses the ..
operator to create a Range
object.
In general, *
flattens arrays, in order to convert a single object into a list of individual arguments to a method. When applied to a non-array object, it will attempt to convert the object into an Array
first by calling to_a
on it. So applying *
to the Range
first calls to_a
on it, which returns an array of the values that lie in the range. That array is then flattened into a list of values by the *
.
Finally, putting that list of values inside square brackets [
...]
generates a new Array
. It's the same result as just calling to_a
on the Range
, but it's gone through a couple extra steps along the way (flattening by *
and unflattening by []
).
Note that on the right hand side of an assignment, you can do without the square brackets, whether literal (x=1,2,3
yields the same result as x=[1,2,3]
) or splatted (x=*2..10
yields the same result as x=[*2..10]
).
The splat operator *
unpacks the receiver's elements in place if the receiver is an array. If the receiver is not an array, implicit class conversion is attempted in advance, using the method to_a
.
In your case, range 2..10
is not an array, so to_a
is attempted, which succeeds because Range#to_a
is defined, and gives [2, 3, 4, 5, 6, 7, 8, 9, 10]
. The splat operator unpacks the elements of that array within the outer []
, resulting in [2, 3, 4, 5, 6, 7, 8, 9, 10]
.
Or (1..5).to_a
.
Also keep in mind that x..y
includes y
in the range, but x...y
includes up until the y
, i.e:
(1...5).to_a
yields [1,2,3,4]
.