## Tuesday, 23 August 2011

### Basic Destructuring

A couple of examples showing destructuring - using the argument list to break up a composite value passed to a function.  The same principle applies within a let statement so it is easy to see how it works.

The function range produces a list of values from a start to an (exclusive) end number with a specified step:
``` user=> (range 1 10 3) (1 4 7) ```

You can omit the step and it will step by 1:
``` user=> (range 1 10) (1 2 3 4 5 6 7 8 9) ```

You can supply just the end and it will start from 0:
``` user=> (range 10) (0 1 2 3 4 5 6 7 8 9) ```

Call it on its own and it will start at 0 and go on as long as you take numbers out:
``` user=> (take 20 (range)) (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19) ```

So, if we pass (range) as a parameter to a let statement, we can deconstruct the first few elements of the list of numbers by using a vector of parameter identifiers like this:
``` user=> (let [[a b c d e f g] (range)] [c e]) [2 4] ```

So in the body of the (let), a=0, b=1, c=2, d=3, e=4, f=5, g=6.

And so [c e] returns [2 4]

The additional character & in the parameter deconstruction sets the following identifier to a vector of the remaining parameters that have not yet been assigned.

And the keyword :as indicates that the next identifier will take the value of the whole list.  Therefore:
``` user=> (let [[a b & c :as d] [1 2 3 4 5]] [a b c d]) [1 2 (3 4 5) [1 2 3 4 5]] ```

What happens here?  From the input values [1 2 3 4 5], a takes the first value 1, b takes the next value 2, and c takes the remaining values and is set to [3 4 5].  Then d is set to the value of the whole input list, that is [1 2 3 4 5].

Compare this with the case where we do not deconstruct the input - we could set d to be the whole of the input list like so:
``` user=> (let [d [1 2 3 4 5]] d) [1 2 3 4 5] ```