Splat Operator in Ruby

In one of my recent posts someone pointed out that using the splat (*) operator would have made some of the code a bit simpler. I’ve seen the splat operator being used in method definitions (to group remaining arguments), but it turns out there are actually quite a few other uses as well.

Method Definitions

def shout_out(message, *friends)
  friends.each { |f| puts "#{f}: #{message}" }
end

shout_out("Hi there!", "Bob", "Steve", "Dave")

Terminal Output

This is probably the most common usage of the splat operator – slurping up all remaining arguments. (Yes, slurping – it’s a technical term) C# developers will probably recognize a similarity to the params keyword in .NET. Ruby is a bit more advanced – we can use it anywhere in the method definition.

def shout_out(message, *friends, signoff)
  friends.each { |f| puts "#{f}: #{message}" }
  puts signoff
end

shout_out("Hi there!", "Bob", "Steve", "Dave", "Pete", "I'll see you later")

Terminal Output

Ruby is clever enough to match up our arguments as best as possible and pass all additional arguments into the splat parameter. What happens if more than one parameter is using the splat operator?

def shout_out(*messages, *friends)
  friends.each do |f|
    messages.each { |m| puts "#{f}: #{m}" }
  end
end

shout_out("Hello!", "How are you?", "Bob", "Steve")

Error Output

Ok, so Ruby doesn’t allow us to do something really stupid. Being able to use the splat operator is really just syntactic sugar – it allows us to pass in additional parameters without having to put those parameters into an array.

Multiple Variable Assignment

Ruby already allows us to do multiple variable assignment without the splat operator (it’s one of my favorite features).

x, y = 10, 20
x, y = y, x
puts "#{x}, #{y}"
# 20, 10

However, there are certain scenarios where we need some extra help.

letters = ["a", "b", "c", "d", "e"]
first, second = letters
puts "#{first}, #{second}"
# a, b

We just lost the last 3 variables! This can be especially useful when you’re working with an array of variable length:

letters = ["a", "b", "c", "d", "e"]
first, *second = letters
puts "#{first}, #{second}"
# a, ["b", "c", "d", "e"]

Flatten Arrays

All the examples we’ve looked at so far involve creating an array out of regular variables. The splat operator can also do the opposite – flattening an array:

some_numbers = [1, 2, 3]
up_to_five = [*some_numbers, 4, 5]
p up_to_five
# [1, 2, 3, 4, 5]

Array Coercion

In some scenarios it can be useful to create arrays out of other variables:

up_to_ten = *1..10
p up_to_ten
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

This is a bit neater than having to use (1..10).to_a. I would be a bit careful of using the splat operator in this way, since you can also start to do a few ridiculous things:

hello = *"Hello"
p hello
# ["Hello"]

It’s obviously important to still keep maintainability in mind when using this operator – just because we can use it doesn’t mean we should.

Conclusion

There are quite a few other scenarios I didn’t cover here – for example, we can use this operator to convert hashes to arrays or call methods with arrays which aren’t really expecting them. While the splat operator can definitely be used effectively in a few niche scenarios it’s very rare to see it being used outside of method definitions. To be honest, I would be careful of using it outside of method definitions, since we don’t want to make the code more complex just to save a few characters here and there.

Happy coding.