---
title: "Ruby splat operator \U0001F31F"
teaser: The Ruby splat operator is confusing and here is why...
tags: web,programming,ruby
author: Sami Birnbaum
published_on: 2022-01-17
---

The Ruby splat operator is confusing and here is why: it does two things that are the exact opposite of each other. Let me explain…

### Destructuring

It **destructures** an array, which looks something like this:

```ruby
x, y, z = *[1,2,3]

puts x
# => 1

puts y
# => 2

puts z
# => 3
```

### Constructing

But it can also be used to **construct** an array:

```ruby
x = *123
# => [123]
```

If you think about this, it is doing two very different things.

One takes an array and **removes** the surrounding square brackets `[]`.

`*[123] becomes 123`

The other takes a value and **adds** the surrounding square brackets `[]`.

`*123 becomes [123]`

### When does it destruct and when does it construct?

The only question we need to answer then is when does it **destruct** and when does it **construct**? 🤔

If you use it when **defining a method** it will take any argument you give it and **construct** it into an array.

```ruby
def describe_args(*args)
  puts args
  puts args.class
end

describe_args(1,2,3)
# 1
# 2
# 3
# Array
```

If you use it when **passing arguments** as an array to a method it will **deconstruct** the array into arguments.

```ruby
def describe_first_arg(x,y,z)
  puts x
  puts x.class
end

describe_first_arg(*[1,2,3])
# 1
# Integer
```

### Practical application

Hopefully, we can now understand a class method you may have come across:

```ruby
def self.perform(*args)
  new(*args).perform
end
```

At first glance this looks strange and complex but using our newfound understanding
of the splat operator we can understand what this is doing.

```ruby
class SumTotal
  def self.perform(*args) # this splat operator will construct any arguments into an array
    new(*args).perform # this splat operator will deconstruct that array into arguments
  end

  def initialize(x,y)
    @x = x
    @y = y
  end

  def perform
   puts @x + @y
  end
end

SumTotal.perform(5,5)
# => 10
```

---

<aside class="info">As an aside, the reason that `perform` is a class method is so you can call `SumTotal.perform()` without having to first instantiate the object like this:</aside>

```ruby
SumTotal.perform(5,5)
# => 10
```

<aside class="info">instead of:</aside>

```ruby
sum_total = SumTotal.new(5,5)
sum_total.perform
# => 10
```

<aside class="info">Using `*args` means that if our expected parameters in the initialize method were to change we would never have to change them in the perform class method, like so:</aside>

```ruby
class SumTotal
  def self.perform(*args)
    new(*args).perform
  end

  def initialize(x,y,z)
    @x = x
    @y = y
    @z = z
  end

  def perform
   puts @x + @y + @z
  end
end

SumTotal.perform(5,5,5)
# => 15
```

The `initialize` and `perform` method have changed but we can make those changes without having to worry about the `self.perform` class method.

---

Thank you to Starr Horne's article [Using splats to build up and tear apart arrays in Ruby]
(https://www.honeybadger.io/blog/ruby-splat-array-manipulation-destructuring/), which helped to shape my understanding.

## Let's work together!

Learn more about [parterning with us](https://thoughtbot.com/services/ruby-on-rails-development) and take the guesswork out of building great products.
