2

What does the * do before 'test' in the below code and across the Ruby programming language?

  def sample (*test)
       puts "The number of parameters is #{test.length}"
       for i in 0...test.length
          puts "The parameters are #{test[i]}"
       end
    end
    sample "Zara", "6", "F"
    sample "Mac", "36", "M", "MCA"
JoshRicha
  • 311
  • 4
  • 18

2 Answers2

7

The last parameter of a method may be preceded by an asterisk(*), which is sometimes called the 'splat' operator. This indicates that more parameters may be passed to the function. Those parameters are collected up and an array is created.

Example:

def sample (*test)
    puts test
end

And call it with:

sample(1,2,3)

Will return array: [1,2,3]

irb(main):001:0> def s(*t)
irb(main):002:1> puts t
irb(main):003:1> end
=> nil
irb(main):004:0> s(1,2,3)
1
2
3
=> nil
0xAX
  • 20,957
  • 26
  • 117
  • 206
  • It's documented here: http://www.ruby-doc.org/core-2.1.2/doc/syntax/methods_rdoc.html#label-Array%2FHash+Argument – Stefan Aug 21 '14 at 13:05
  • Use `p` instead of `puts` to make the output more readable and less ambiguous, since it will print `[1,2,3]` – Uri Agassi Aug 21 '14 at 13:09
  • Note that in latest versions of ruby, it doesn't have to be the last parameter... `(*items, var)` works and assigns all arguments but the last to `items` array and assigns the last to `var`... similarly you can have embedded... `(first_var, *items, last_var)` which assigns first argument to `first_var`, last argument to `last_var` and all arguments between first and last to the `items` array. – SteveTurczyn Aug 21 '14 at 13:37
2

OxAX mentioned one good use of the * prefix operator - to collect arguments and this is what it does in your example.

def lots_of_args *args
  p args
end
lots_of_args 1,2,3 # => [1, 2, 3]

first, *rest = 1, 2, 3, 4
first # => 1
rest  # => [2, 3, 4]

We can even apply it outside of method definitions.


However, it's important to note that there's another good use for it:

def add_three_nums a, b, c
  a + b + c
end

add_three_nums *[1,2,3]  # => 6
# same as calling "add_three_nums 1,2,3"

Essentially, the * operator expands a method argument that's an array into a list of arguments.


There's even a third use case:

first, *rest = [1, 2, 3, 4]
first # => 1
rest  # => [2, 3, 4]

This third case is somewhat similar to the first. However, notice that we get the values of first and rest from an array, not from a list of values.


JKillian
  • 18,061
  • 8
  • 41
  • 74