Search code examples
rubyoperatorsinversesplat

Is it possible to invert a splat in Ruby?


Ruby's splat operator * may be used to coalesce

def one_argument(*a)
  ...
end

one_argument(1, 2, 3)

or split

def multiple_arguments(a, b, c)
  ...
end

multiple_arguments(*[1, 2, 3])

multiple values, depending on the context.

Is it possible to create a method that acts as an "inverse splat" operator? To act as an inverse, the operator must satisfy:

inverse_splat(*(foo)) == foo

and

*(inverse_splat(foo)) == foo

Solution

    • Regarding *(inverse_splat(foo)), it does not make sense. The result of splatting is in general a sequence of objects, which is not an object. Such thing cannot exist in Ruby.

      And at this point, the assumption you seem to making, i.e., that the order of inverse_splat and * are interchangable, turns out to be false.

    • Regarding inverse_splat(*(foo))

      There cannot be such inverse. That is because the splat * internally calls to_a, which is not a one-to-one mapping.

      [[:a, 1], [:b, 2]].to_a
      # => [[:a, 1], [:b, 2]]
      {a: 1, b: 2}.to_a
      # => [[:a, 1], [:b, 2]]
      

      An inverse can only be defined on a one-to-one map.

      If you disregard such cases and want to still explore if there is something close to it, then a close thing is the [...] literal.