**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]