Search code examples
rubyarraysblock

Destructuring Ruby block arguments dynamically


A recent good article on ruby destructuring defines destructuring as ability to bind a set of variables to a corresponding set of values anywhere that you can normally bind a value to a single variable, and gives an example of block destructuring

triples = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

triples.each { |(first, second, third)| puts second } =>#[2, 5, 8]

In this case we have an idea of the number of elements in the main array and therefore when we provide the arguments first,second,third we can get the corresponding result. So what about if we had an array of arrays whose size is determined at run-time?

triples = [[1, 2, 3], [4, 5, 6], [7, 8, 9],...,[]]

and we would want to get the elements of the first entry for each subarray?

triples.each { |(first, second, third,...,n)| puts first }

what is the best way to create the local variables (first, second, third,...,n) dynamically?


Solution

  • In your specific case, you'd use a splat to collect up everything but the first value:

    triples.each { |first, *rest| puts first }
    #-----------------------^splat
    

    The *rest notation just collects everything that's left into an Array called rest.

    In general, there's not much point to creating an arbitrary number of local variables (second, third, ..., nth) because you wouldn't be able to do anything with them; you could probably whip up a sick mess of evals but we already have a fine and functional Array class so why bother?