Reason #96 • April 6th, 2026

Argument splatting

When we already have values collected in an array or hash, Ruby lets us expand them directly into a method call using * and **. * turns an array into positional arguments, while ** turns a hash into keyword arguments.

Ruby
def build_url(host, path, protocol: "https", port: 443)
  "#{protocol}://#{host}:#{port}#{path}"
end

segments = ["example.com", "/docs"]
options = { protocol: "http", port: 3000 }

build_url(*segments, **options)
# => "http://example.com:3000/docs"

def proxy_call(*args, **kwargs)
  build_url(*args, **kwargs)
end

proxy_call("rubylang.org", "/en", port: 80)
# => "https://rubylang.org:80/en"
    

There is a beautiful symmetry in this syntax: the same *args and **kwargs syntax we use to capture arguments in a method definition is also used to forward them elsewhere. Useful for wrapper methods, delegation and little bits of metaprogramming.

History

Expanding positional arguments with * has been part of Ruby since its inception.

Expanding keyword arguments with ** arrived together with keyword arguments in Ruby 2.0, released in 2013.

Ruby 3.0, released on Christmas 2020, fully separated keyword arguments from positional hashes. That made splatting with ** more explicit and predictable, especially when forwarding arguments between methods.

The original argument expansion may have been inspired by Perl, which implicitly splats arrays and hashes when used in a method call, though it is worth noting that Python uses the same * and ** syntax for argument unpacking as well.

Som interesting discussion on the design of Ruby's keyword arguments can be found on the Ruby issue tracker: https://bugs.ruby-lang.org/issues/5474

Reason #97 ?