Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
Ruby Pearls vol. 1 – The Splat

Over the next week or so I’ll be sharing Ruby idioms and flourishes that I quite like. Today I’d I’ll show a few tiny uses of splat! that make me tremble with delight.

Splat! – For Beginners

Splat! is the star (*) operator, typically used in Ruby for defining methods that take an unlimited number of arguments:

def sprintf(string, *args)
end

It can also be used to convert an array to the multiple-argument form when invoking a function:

some_ints = [1,2,3]
sprintf("%%i %%i %%i", *some_ints)

Splat! – For Wizards

Array to Hash Conversion

The best use of splat! for invoking a infinite-arity functions I’ve ever seen is the recipe for converting an array to a hash. Suppose you have an array of pairs:

array = [[key_1, value_1], [key_2, value_2], ... [key_n, value_n]]

You would like to produce from it the hash: {key1 => value1 ... } You could inject down the array, everybody loves inject, but there is a better way:

Hash[*array.flatten]

Amazing right? This relies on the the fact that the Hash class implements the [] (brackets) operator and behaves thusly:

Hash[key1, value1, ...] = { key1 => value1, ... }

Heads or tails?

Splat! can be used for more than just method definition and invocation. My personal favorite use is destructuring assignment. I read this in Active Record’s source code recently:

  def sanitize_sql_array(ary)
    statement, *values = ary
    ...
  end

This is invoked when you do something like User.find(:all, :conditions => ['first_name = ? and last_name = ?', 'nick', 'kallen']). Splat! is used here is to get the head and tail of the conditions array. Of course, you could use always use shift, but the functional style used here is quite beautiful. Consider another example:

first, second, *rest = ary

One final trivium (#to_splat aka #to_ary)

You can actually customize the behavior of the splat operator. In Ruby 1.8, implement #to_ary and in 1.9 it’s #to_splat. For example

class Foo
  def to_ary
    [1,2,3]
  end
end

a, *b = Foo.new
a # => 1
b # => [2,3]

This also works for method invocation:

some_method(*Foo.new) == some_method(1,2,3)

When I first learned this at RubyConf I thought this was mind-blowing. I have since never used it.

Comments
  1. Neeraj says:

    I recently posted similar question to the forum http://www.ruby-forum.com/topic/150123#new

    Thanks for the series.

  2. Tom Ward says:

    My favourite:
    regex = /([^ ]*) ([^ ]*)/
    match, first_name, last_name = *”Tom Ward”.match(regex)

  3. Tom Ward says:

    Or better formatted (hopefully):

    regex = /([^ ]*) ([^ ]*)/
    match, first_name, last_name = *”Tom Ward”.match(regex)

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *