Unpack the other end: last and init

last(L) returns the last element. init(L) returns the list without its final position. For [3,13,23,25], last is 25 and init is [3,13,23]. These complement first and rest. On a singleton, init gives []; on an empty list the tutorial defines init as [], but last has no defined element.
![For non-empty L, [first(L)] ++ rest(L) and init(L) ++ [last(L)] both rebuild L.](/images/computational-thinking/week-5/reconstruct.png)
# For a NON-EMPTY list L:
L == [first(L)] ++ rest(L)
L == init(L) ++ [last(L)]first and last may return complex elements too. If L is a list of pairs, first(L) is an entire pair. Wrapping it in [first(L)] makes a singleton OUTER list. Bracket levels carry meaning.
For a known non-decreasing list of numeric marks, first gives its minimum and last its maximum, so the range is last(L) − first(L). This shortcut is invalid on an arbitrary unsorted list. A short expression also does not guarantee constant-time execution: the tutorial implements last with a full foreach scan.
Try it yourself
What is init([3,13,3])?
Show explained answer
[3,13]. Only the last occurrence is dropped, even though its value also appears at the start.
Try it yourself
Can you use last(L) − first(L) to find the range of [68,42,97,62]?
Show explained answer
No. It gives 62 − 68, not the true range 97 − 42 = 55. The endpoint shortcut needs sorted order.
Try it yourself
Why are the brackets in [first(L)] needed?
Show explained answer
first(L) is an element. ++ requires list operands, so the element must be wrapped in a singleton list.
