From b63e280ab577c442f468f8ba047be3b124d106ac Mon Sep 17 00:00:00 2001 From: Jim Pryor Date: Mon, 4 Oct 2010 23:00:45 -0400 Subject: [PATCH] week4 f-->f2 Signed-off-by: Jim Pryor --- week4.mdwn | 74 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/week4.mdwn b/week4.mdwn index e2805fb3..f3d7c030 100644 --- a/week4.mdwn +++ b/week4.mdwn @@ -453,25 +453,25 @@ Do you have the basic idea? Think about how you'd implement it. A good understanding of the v2 lists will give you a helpful model. In broad outline, a single stage of the search would look like before, except -now `f` would receive two extra, "handler" arguments. +now `f` would receive two extra, "handler" arguments. We'll reserve the name `f` for the original fold function, and use `f2` for the function that accepts two additional handler arguments. To get the general idea, you can regard these as interchangeable. If the extra precision might help, then you can pay attention to when we're talking about the handler-taking `f2` or the original `f`. You'll only be *supplying* the `f2` function; the idea will be that the behavior of the original `f` will be implicitly encoded in `f2`'s behavior. - f 3 + f2 3 -`f`'s job would be to check whether `3` matches the element we're searching for +`f2`'s job would be to check whether `3` matches the element we're searching for (here also `3`), and if it does, just evaluate to the result of passing `true` to the abort handler. If it doesn't, then evaluate to the result of passing `false` to the continue-leftwards handler. -In this case, `f` wouldn't need to consult the result of folding `f` and `z` over `[2; -1]`, since if we had found the element `3` in more rightward positions of the -list, we'd have called the abort handler and this application of `f` to `3` etc -would never be needed. However, in other applications the result of folding `f` -and `z` over the more rightward parts of the list would be needed. Consider if -you were trying to multiply all the elements of the list, and were going to -abort (with the result `0`) if you came across any element in the list that was -zero. If you didn't abort, you'd need to know what the more rightward elements -of the list multiplied to, because that would affect the answer you passed -along to the continue-leftwards handler. +In this case, `f2` wouldn't need to consult the result of folding `f` and `z` +over `[2; 1]`, since if we had found the element `3` in more rightward +positions of the list, we'd have called the abort handler and this application +of `f2` to `3` etc would never be needed. However, in other applications the +result of folding `f` and `z` over the more rightward parts of the list would +be needed. Consider if you were trying to multiply all the elements of the +list, and were going to abort (with the result `0`) if you came across any +element in the list that was zero. If you didn't abort, you'd need to know what +the more rightward elements of the list multiplied to, because that would +affect the answer you passed along to the continue-leftwards handler. A **version 5** list encodes the kind of fold operation we're envisaging here, in the same way that v3 (and [v4](/advanced_lambda/#index1h1)) lists encoded @@ -479,39 +479,39 @@ the simpler fold operation. Roughly, the list `[5;4;3;2;1]` would look like this: - \f z continue_leftwards_handler abort_handler. - - (\result_of_fold_over_4321. f 5 result_of_fold_over_4321 continue_leftwards_handler abort_handler) + \f2 z continue_leftwards_handler abort_handler. + + (\result_of_folding_over_4321. f2 5 result_of_folding_over_4321 continue_leftwards_handler abort_handler) abort_handler ; or, expanding the fold over [4;3;2;1]: - \f z continue_leftwards_handler abort_handler. + \f2 z continue_leftwards_handler abort_handler. (\continue_leftwards_handler abort_handler. - - (\result_of_fold_over_321. f 4 result_of_fold_over_321 continue_leftwards_handler abort_handler) + + (\result_of_folding_over_321. f2 4 result_of_folding_over_321 continue_leftwards_handler abort_handler) abort_handler ) - (\result_of_fold_over_4321. f 5 result_of_fold_over_4321 continue_leftwards_handler abort_handler) + (\result_of_folding_over_4321. f2 5 result_of_folding_over_4321 continue_leftwards_handler abort_handler) abort_handler - ; and so on + ; and so on Remarks: the `larger_computation` handler should be supplied as both the `continue_leftwards_handler` and the `abort_handler` for the leftmost -application, where the head `5` is supplied to `f`; because the result of this +application, where the head `5` is supplied to `f2`; because the result of this application should be passed to the larger computation, whether it's a "fall off the left end of the list" result or it's a "I'm finished, possibly early" result. The `larger_computation` handler also then gets passed to the next -rightmost stage, where the head `4` is supplied to `f`, as the `abort_handler` to +rightmost stage, where the head `4` is supplied to `f2`, as the `abort_handler` to use if that stage decides it has an early answer. -Finally, notice that we don't have the result of applying `f` to `4` etc given as -an argument to the application of `f` to `5` etc. Instead, we pass +Finally, notice that we don't have the result of applying `f2` to `4` etc given as +an argument to the application of `f2` to `5` etc. Instead, we pass - (\result_of_fold_over_4321. f 5 result_of_fold_over_4321 ) + (\result_of_foldiing_over_4321. f2 5 result_of_folding_over_4321 ) -*to* the application of `f` to `4` as its "continue" handler. The application of `f` +*to* the application of `f2` to `4` as its "continue" handler. The application of `f2` to `4` can decide whether this handler, or the other, "abort" handler, should be given an argument and constitute its result. @@ -530,24 +530,24 @@ fixed evaluation order and you'll be able to program efficiently around that. In detail, then, here's what our v5 lists will look like: - let empty = \f z continue_handler abort_handler. continue_handler z in - let make_list = \h t. \f z continue_handler abort_handler. - t f z (\sofar. f h sofar continue_handler abort_handler) abort_handler in + let empty = \f2 z continue_handler abort_handler. continue_handler z in + let make_list = \h t. \f2 z continue_handler abort_handler. + t f2 z (\sofar. f2 h sofar continue_handler abort_handler) abort_handler in let isempty = \lst larger_computation. lst - ; here's our f + ; here's our f2 (\hd sofar continue_handler abort_handler. abort_handler false) ; here's our z true - ; here's the continue_handler for the leftmost application of f + ; here's the continue_handler for the leftmost application of f2 larger_computation ; here's the abort_handler larger_computation in let extract_head = \lst larger_computation. lst - ; here's our f + ; here's our f2 (\hd sofar continue_handler abort_handler. continue_handler hd) ; here's our z junk - ; here's the continue_handler for the leftmost application of f + ; here's the continue_handler for the leftmost application of f2 larger_computation ; here's the abort_handler larger_computation in @@ -578,7 +578,7 @@ detail](http://okmij.org/ftp/Streams.html#enumerator-stream). > **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, +> 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 @@ -593,8 +593,8 @@ detail](http://okmij.org/ftp/Streams.html#enumerator-stream). > 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 +> let make_list = \h t. \f2 z continue_handler abort_handler. +> f2 h z (\z. t f2 z continue_handler abort_handler) abort_handler > > now `extract_head` should return the leftmost head directly, using its > `abort_handler`: -- 2.11.0