Down the Ruby Mine, Part III: Splat and splat again

Posted by on August 29, 2019

Hello and welcome to another Down the Ruby Mine. I’m Sam, one of the Engineering Interns working at FreeAgent over the Summer and I am here to shed some light on a Ruby language feature. If you’re out of the loop, you may have missed my previous posts which can be found here and here. Today we’ll be diving into the most questionably named Ruby feature out there: splat.

Functions are a developer’s best friend. They allow you to make your code more modular and readable without significant efficiency costs. A common roadblock that developers come up against, is allowing functions to take a variable number of arguments. Fortunately, Ruby provides two useful mechanisms for doing just that.

The * or splat operator converts an array into a list of arguments and vice versa. If we want to feed arguments from an array into a function we can do the following:

def show_arguments(arg1, arg2, arg3)
  puts arg1
  puts arg2
  puts arg3
end

argument_array = ["Arg1", "Arg2", "Arg3"]

show_arguments(*argument_array)
# Arg1
# Arg2
# Arg3

Notice that by using the splat operator we can feed in each element of the array as a separate argument. Splat does not have to be used alone in a function call, it can be used alongside other arguments:

def show_arguments(arg1, arg2, arg3, arg4)
  puts arg1
  puts arg2
  puts arg3
  puts arg4
end

argument_array = ["Arg2", "Arg3"]

show_arguments("Arg1", *argument_array, "Arg4")
# Arg1
# Arg2
# Arg3
# Arg4

Approaching from a different angle, the splat operator can be included in the function declaration. This allows a variable number of arguments to be gathered into an array that is accessible from within the function:

def show_arguments(*arg_array)
  arg_array.each do |arg|
    puts arg
  end
end

show_arguments("Arg1", "Arg2", "Arg3")
# Arg1
# Arg2
# Arg3

argument_array = ["Arg1", "Arg2", "Arg3"]
show_arguments(*argument_array)
# Arg1
# Arg2
# Arg3

Splat works well for positional arguments but does not provide any benefits if your function takes in keyword arguments. Luckily we can use the ** or double splat to resolve this. (Yes, Ruby devs have really thought of everything!)

In the same way that splat allows arrays to be decomposed into arguments, double splat extends this to hashes. Below we can see that a double splat-ed hash can be used on a function that takes in keyword arguments:

def show_arguments(first: "first", second: "second")
  puts first
  puts second
end

show_arguments
# first
# second

argument_hash = {first: "new_first", second: "new_second"}
show_arguments(**argument_hash)
# new_first
# new_second 

Similarly if you add the double splat in the function declaration, keyword arguments are parsed into a dictionary which can be used inside the function:

def show_arguments(**arg_hash)
  arg_hash.each do |key, value|
    puts key
    puts value
  end
end

show_arguments
# 

show_arguments(first: "first_arg", second: "second_arg")
# first
# first_arg
# second
# second_arg

If you really want to impress your friends, you can combine both splat and double splat into what is not-so-commonly-known-as a multi-splat-function. This is useful when you want to receive a variable number of optional positional and keyword arguments:

def show_arguments(main_argument, *additional_positional, **additional_keyword)
  puts main_argument

  additional_positional.each do |positional_arg|
    puts "Positional: #{positional_arg}"
  end

  additional_keyword.each do |keyword_arg_key, keyword_arg_value|
    puts "Keyword: key -- #{keyword_arg_key}, value -- #{keyword_arg_value}"
  end
end

show_arguments("main_arg")
# main_arg

show_arguments("main_arg", first: "first_arg", second: "second_arg")
# main_arg
# Keyword: key -- first, value -- first_arg
# Keyword: key -- second, value -- second_arg


show_arguments("main_arg", "other_arg", first: "first_arg", second: "second_arg")
# main_arg
# Positional: other_arg
# Keyword: key -- first, value -- first_arg
# Keyword: key -- second, value -- second_arg

When calling a function the splat operators can be used to turn an array or hash into a list of arguments. Additionally, they allow a variable number of arguments to be gathered up into an array or dictionary within a function. They are two important tools in any Ruby developer’s toolbox, so go out there and use them without hesitation!

I hope that this trio of Ruby tidbits has sated your thirst for language features. As a software engineering intern at FreeAgent, I have been developing an understanding of Ruby and a multitude of cool Rails features throughout my time here. Everyone has been friendly and helpful, happy to answer questions and provide constructive criticism. One thing that has continually stood out to me during my time at FreeAgent is the constant cross-team communication. As cliché as it sounds working here is like being part of a family, one with technically-literate, modern parents and supportive siblings.

Leave a reply

Your email address will not be published. Required fields are marked *