rename topics/week13_control_operators.mdwn to topics/week13_native_continuation_oper...
[lambda.git] / topics / week12_abortable_traversals.mdwn
index 59d5517..7cccacb 100644 (file)
@@ -63,11 +63,10 @@ Here's how to get the last element of such a list:
 
 This is similar to getting the first element, except that each step delivers its output to the `keep_going` handler rather than to the `done` handler. That ensures that we will only get the output of the last step, when the traversal function is applied to the last member of the list. If the list is empty, then we'll get the `err` value, just as with the function that tries to extract the list's head.
 
-One thing to note is that there are limits to how much you can immunize yourself against doing unnecessary work. A demon evaluator who got to custom-pick the evaluation order (including doing reductions underneath lambdas when he wanted to) could ensure that lots of unnecessary computations got performed, despite your best efforts. We don't yet have any way to prevent that. (Later we will see some ways to *computationally force* the evaluation order we prefer. Of course, in any real computing environment you'll mostly know what evaluation order you're dealing with, and you can mostly program efficiently around that.) The current scheme at least makes our result not *computationally depend on* what happens further on in the traversal, once we've passed a result to the `done_handler`. We don't even depend on the later steps in the traversal cooperating to pass our result through.
+One thing to note is that there are limits to how much you can immunize yourself against doing unnecessary work. A demon evaluator who got to custom-pick the evaluation order (including doing reductions underneath lambdas when he wanted to) could ensure that lots of unnecessary computations got performed, despite your best efforts. We don't yet have any way to prevent that. (Later we will see some ways to *computationally force* the evaluation order we prefer. Of course, in any real computing environment you'll mostly know what evaluation order you're dealing with, and you can mostly program efficiently around that.) The current scheme at least makes our result not *computationally depend on* what happens further on in the traversal, once we've passed a result to the `done_handler`. We don't even rely on the later steps in the traversal cooperating to pass our result through.
 
-All of that gave us a left-fold implementation of lists. (Perhaps if you were _aiming_ for a left-fold implementation of lists, you would make the traversal function `f` take its `current_list_element` and `seed_value` arguments in the flipped order, but let's not worry about that.)
-
-Now, let's think about how to get a right-fold implementation. It's not profoundly different, but it does require us to change our interface a little. Our left-fold implementation of `[10,20,30,40]`, above, looked like this (now we abbreviate some of the variables):
+All of that gave us a *left*-fold implementation of lists. (Perhaps if you were _aiming_ for a left-fold implementation of lists, you would make the traversal function `f` take its `current_list_element` and `seed_value` arguments in the flipped order, but let's not worry about that.)
+Now, let's think about how to get a *right*-fold implementation. It's not profoundly different, but it does require us to change our interface a little. Our left-fold implementation of `[10,20,30,40]`, above, looked like this (now we abbreviate some of the variables):
 
     \f z d. f 10 z d (\z. [20,30,40] f z d)
 
@@ -85,7 +84,7 @@ Now suppose we had just the implementation of the tail of the list, `[20,30,40]`
 
 How should we take that value and transform it into the preceding value, which represents `10` consed onto that tail? I can't see how to do it in a general way, and I expect it's just not possible. Essentially what we want is to take that second `d` in the innermost function `\z. f 20 z d d`, we want to replace that second `d` with something like `(\z. f 10 z d d)`. But how can we replace just the second `d` without also replacing the first `d`, and indeed all the other bound occurrences of `d` in the expansion of `[20,30,40]`.
 
-The difficulty here is that our traversal function `f` expects two handlers, but we are only giving the fold function we implement the list as a single handler. That single handler gets fed twice to the traversal function. One time it may be transformed, but at the end of the traversal, as with `\z. f 20 z d d`, there's nothing left to do to "keep going", so here it's just the single handler `d` fed to `f` twice. But we can see that in order to implement `cons` for a right-folding traversal, we don't want it to be the single handler `d` fed to `f` twice. It'd work better if we implemented `[20,30,40]` like this:
+The difficulty here is that our traversal function `f` expects two handlers, but we are only giving a single handler to the fold function we implement the list as. That single handler gets fed twice to the traversal function. One time it may be transformed, but at the end of the traversal, as with `\z. f 20 z d d`, there's nothing left to do to "keep going", so here it's just the single handler `d` fed to `f` twice. But we can see that in order to implement `cons` for a right-folding traversal, we don't want it to be the single handler `d` fed to `f` twice. It'd work better if we implemented `[20,30,40]` like this:
 
     \f z d g. f 40 z d (\z. f 30 z d (\z. f 20 z d g))