-*Comments*:
-
-1. The technique deployed here, and in the v2 lists, and in our implementations
- of pairs and booleans, is known as **continuation-passing style** programming.
-
-2. We're still building the list as a right fold, so in a sense the
- application of `f` to the leftmost element `5` is "outermost". However,
- this "outermost" application is getting lifted, and passed as a *handler*
- to the next right application. Which is in turn getting lifted, and
- passed to its next right application, and so on. So if you
- trace the evaluation of the `extract_head` function to the list `[5;4;3;2;1]`,
- you'll see `1` gets passed as a "this is the head sofar" answer to its
- `continue_handler`; then that answer is discarded and `2` is
- passed as a "this is the head sofar" answer to *its* `continue_handler`,
- and so on. All those steps have to be evaluated to finally get the result
- that `5` is the outer/leftmost head of the list. That's not an efficient way
- to get the leftmost head.
-
- We could improve this by building lists as left folds when implementing them
- as continuation-passing style folds. We'd just replace above:
-
- let make_list = \h t. \f z continue_handler abort_handler.
- f h z (\z. t f z continue_handler abort_handler) abort_handler
-
- now `extract_head` should return the leftmost head directly, using its `abort_handler`:
-
- let extract_head = \lst larger_computation. lst
- (\hd sofar continue_handler abort_handler. abort_handler hd)
- junk
- larger_computation
- larger_computation
-
-3. To extract tails efficiently, too, it'd be nice to fuse the apparatus developed
- in these v5 lists with the ideas from [v4](/advanced/#v4) lists.
- But that also is left as an exercise.
+> *Comments*:
+
+> 1. The technique deployed here, and in the v2 lists, and in our
+> implementations of pairs and booleans, is known as
+> **continuation-passing style** programming.
+
+> 2. We're still building the list as a right fold, so in a sense the
+> application of `f2` to the leftmost element `5` is "outermost". However,
+> this "outermost" application is getting lifted, and passed as a *handler*
+> to the next right application. Which is in turn getting lifted, and
+> passed to its next right application, and so on. So if you
+> trace the evaluation of the `extract_head` function to the list `[5;4;3;2;1]`,
+> you'll see `1` gets passed as a "this is the head sofar" answer to its
+> `continue_handler`; then that answer is discarded and `2` is
+> passed as a "this is the head sofar" answer to *its* `continue_handler`,
+> and so on. All those steps have to be evaluated to finally get the result
+> that `5` is the outer/leftmost head of the list. That's not an efficient way
+> to get the leftmost head.
+>
+> We could improve this by building lists as **left folds**. What's that?
+>
+> Well, the right fold of `f` over a list `[a;b;c;d;e]`, using starting value z, is:
+>
+> f a (f b (f c (f d (f e z))))
+>
+> The left fold on the other hand starts combining `z` with elements from the left. `f z a` is then combined with `b`, and so on:
+>
+> f (f (f (f (f z a) b) c) d) e
+>
+> or, if we preferred the arguments to each `f` flipped:
+>
+> f e (f d (f c (f b (f a z))))
+>
+> Recall we implemented v3 lists as their own right-fold functions. We could
+> instead implement lists as their own left-fold functions. To do that with our
+> v5 lists, we'd replace above:
+>
+> let make_list = \h t. \f2 z continue_handler abort_handler.
+> f2 h z (\z. t f2 z continue_handler abort_handler) abort_handler
+>
+> Having done that, now `extract_head` can return the leftmost head
+> directly, using its `abort_handler`:
+>
+> let extract_head = \lst larger_computation. lst
+> (\hd sofar continue_handler abort_handler. abort_handler hd)
+> junk
+> larger_computation
+> larger_computation
+>
+> 3. To extract tails efficiently, too, it'd be nice to fuse the apparatus
+> developed in these v5 lists with the ideas from
+> [v4](/advanced_lambda/#index1h1) lists. But that is left as an exercise.