0

I am a newbie in Ruby. Please explain how the * operator works in this case.

arr = [1,2,3]
p arr
arr = *[1,2,3]
p arr
*arr = [1,2,3]
p arr
arr = [1,2,3]
p *arr

OUTPUT

[1,2,3]

[1,2,3]

[1,2,3]

1

2

3

What is happening in the last case ? Is it behaving as a iterator ? Can anyone give an example as to how to use it ? Also why it has no effect in the second and third case ?

Steve Mitcham
  • 5,268
  • 1
  • 28
  • 56
sid_09
  • 461
  • 4
  • 18
  • Same question here : http://stackoverflow.com/questions/1729284/ruby-what-does-the-asterisk-in-p-1-10-mean – limekin Feb 23 '15 at 14:11
  • possible duplicate of [What does the \* (star) mean in Ruby?](http://stackoverflow.com/questions/4170037/what-does-the-star-mean-in-ruby) – WattsInABox Feb 23 '15 at 15:55

2 Answers2

0

The "*" operator on an array in that context, turns an array into a list of arguments.

Let's say you have a method that takes three arguments:

def takes_three(one, two, three)
  puts "first: #{one}, second: #{two}, third: #{three}"
end

If you tried to do this:

arr = ["a", "b", "c"]
takes_three(arr)
# => ArgumentError: wrong number of arguments (1 for 3)

Your method takes three arguments, but you only passed it one -- that one was an array.

If you want to turn the array of three elements into three separate arguments to the method, that's what * does here:

takes_three(*arr)
# => puts "first: a, second: b, third: c"

What gets confusing in your examples, believe it or not, is your use of p, shortcut in irb for puts. puts takes a variable number of arguments, you can give it however many you want. It will output them all, separated by newlines. And if you give it a single array argument, it will still output each element in the array separated by newlines.

irb(main):068:0> puts ["a", "b", "c"]
a
b
c
irb(main):069:0> puts "a", "b", "c"
a
b
c
irb(main):070:0> puts arr
a
b
c
irb(main):071:0> puts *arr
a
b
c

Since puts "a", "b", "c" and puts ["a", "b", "c"] do the same thing, puts arr and puts *arr do the same thing too. Since puts *arr is equivalent to puts 1, 2, 3, it expands an array into separate arguments for the method.

So your attempt to investigate with puts makes it confusing, because puts takes a variable number of arguments, and does the same thing with one argument that's an array of n elements, as it does with n separate arguments each of those elements. Most methods don't work that way though, so for most methods *, changing the nature of the arguments you're giving to the method, will also change what the method does. It is useful for a kind of indirection, where you build up the arguments you want to pass in an array dynamically, instead of writing them fixed in source code.

jrochkind
  • 22,799
  • 12
  • 59
  • 74
0

That is the splat operator (*). It can be used to expand the array in a method call to list of argument or in some assignment to to a 'take all'. Below is some example:

1) Using pass array to method call as list of arguments

Given the following method:

def my_method(argument1, argument2, argument3)
end

You can turn an Array into an argument list with * (or splat) operator:

arguments = [1, 2, 3]
my_method(*arguments)

https://ruby-doc.org/core-2.2.0/doc/syntax/calling_methods_rdoc.html

2) using with assignment to to 'take all'

*, sometimes called the "splat operator," does a number of things with arrays. When it's on the left side of an assignment operator (=), as in your example, it just means "take everything left over."

Example:

a = [1, 2, 3, 4, 5]
head, *tail = a
p head #=> 1
p tail #=> [2, 3, 4, 5]

If you omitted the splat in that code, it would do this instead:

head, tail = [1, 2, 3, 4, 5]
p head # => 1
p tail # => 2

But when you add the splat to tail it means "Everything that didn't get assigned to the previous variables (head), assign to tail."

source: What does this mean in Ruby language?

Community
  • 1
  • 1
suhao399
  • 628
  • 7
  • 11