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]
No comments:
Post a Comment