What does the syntax [* a..b] mean in Ruby?

NOTE. mischa splat on GitHub contains many interesting interactive examples * in action.

By googling, I found that one way to iterate over a range of numbers in Ruby (your classic C-style loop for a loop)

for (i = first; i <= last; i++) { whatever(i); } 

should do something like this

 [*first..last].each do |i| whatever i end 

But what exactly happens with this syntax [*first..last] ? I played with irb and I see this:

 ruby-1.9.2-p180 :001 > 0..5 => 0..5 ruby-1.9.2-p180 :002 > [0..5] => [0..5] ruby-1.9.2-p180 :003 > [*0..5] => [0, 1, 2, 3, 4, 5] ruby-1.9.2-p180 :004 > *0..5 SyntaxError: (irb):4: syntax error, unexpected tDOT2, expecting tCOLON2 or '[' or '.' *0..5 ^ 

Everything I've read on the Internet discusses a unary asterisk as useful for expanding and collapsing arguments passed to a method, useful for variable-length argument lists

 def foo(*bar) bar end foo 'tater' # => ["tater"] foo 'tater', 'tot' # => ["tater", "tot"] 

and I get this, but I donโ€™t see how this relates to the extension running in my example block above.

To be clear, I know that The Ruby Way is intended to iterate over an array or collection, and not to use the length of the array and iterate through an integer index. However, in this example, I am really dealing with a list of integers. :)

+8
operators syntax ruby splat
source share
3 answers
 [*1..10] 

is the same as

 (1..10).to_a # call the "to array" method 

The instances of the Array class that you created implement Enumerable , so your loop works. In classes that define the to_a method, you can use the syntax of the splat operator with parentheses. Splat does much more than just call #to_a , although it will cost Google a search on its own.

Now, in your case, the Range class itself is already Enumerable , so you can just do:

 (first..last).each do |v| ... end 
+12
source share

It is called the splat operator. If you use it in certain positions, such as the position of an argument or an array, it will expand into its elements:

 a = [1] [*a, 3] # => [1, 3] b = [1, 2] [*b, 3] # => [1, 2, 3] 

You cannot use it naked or in ranges:

 *a..3 # => error. (*a..3) # => error. 

When you have something that is not an array, it returns itself:

 a = 1 [*a, 3] # => [1, 3] 
+3
source share

[first..last] is an array containing only one range object. [*first..last] is an array containing elements of this range that were sent as a list of arguments. * works in the context of a list of arguments.

+3
source share

All Articles