tweak calc improvements
authorJim Pryor <profjim@jimpryor.net>
Thu, 25 Nov 2010 16:47:53 +0000 (11:47 -0500)
committerJim Pryor <profjim@jimpryor.net>
Thu, 25 Nov 2010 16:47:53 +0000 (11:47 -0500)
Signed-off-by: Jim Pryor <profjim@jimpryor.net>
advanced_topics/calculator_improvements.mdwn

index cbf4c89..f6f179f 100644 (file)
@@ -184,7 +184,7 @@ Here is the expanded definition for our language type:
                | Apply of (term * term)
                | Letrec of (char * term * term);;
 
-Now consider what we'll need to do when evaluating a term like `Letrec ('f', Lambda (...), t2)`. The subterm `Lambda (...)` will evaluate to something of the form `Closure ('y', body, savedg)`, where `f` may occur free in `body`. What we'll want to do is to ensure that when `body` is applied, it's applied using not the assignment `savedg` but a modified assignment `savedg'` which binds `f` to this very function value. That is, we want to bind `f` not to:
+Now consider what we'll need to do when evaluating a term like `Letrec ('f', Lambda (...), t2)`. The subterm `Lambda (...)` will evaluate to something of the form `Closure ('y', body, savedg)`, where `Variable 'f'` may occur free in `body`. What we'll want to do is to ensure that when `body` is applied, it's applied using not the assignment `savedg` but a modified assignment `savedg'` which binds `'f'` to this very function value. That is, we want to bind `'f'` not to:
 
        Closure ('y', body, savedg)
 
@@ -197,9 +197,9 @@ but instead to:
 
 Except, this isn't quite right. It's almost what we want, but not exactly. Can you see the flaw?
 
-The flaw is this: inside `new_closure`, what is `f` bound to? It's bound by `savedg'` to `orig_closure`, which in turn leaves `f` free (or bound to whatever existing value it had according to `savedg`). This isn't what we want. It'll break if we need to make recursive calls to `f` which go more than two levels deep.
+The flaw is this: inside `new_closure`, what is `'f;` bound to? It's bound by `savedg'` to `orig_closure`, which in turn leaves `'f'` free (or bound to whatever existing value it had according to `savedg`). This isn't what we want. It'll break if we need to make applications of `Variable 'f'` which recurse more than once.
 
-What we really want is for `f` to be bound to `new_closure`, something like this:
+What we really want is for `'f'` to be bound to `new_closure`, something like this:
 
        let rec new_closure = Closure ('y', body, ('f', new_closure) :: savedg)
        in new_closure
@@ -245,7 +245,7 @@ The way we'll do this is that, when we bind a value to a variable, we'll keep tr
                Letrec ('f', Lambda ('y', Variable 'f')),
                ...)
 
-In the first case, an application of `f` to any argument should evaluate to `Int 1`; in the second case, it should evaluate to the same function closure that `f` evaluates to. We'll keep track of which way a variable was bound by expanding our `bound_value` type:
+In the first case, an application of `Variable 'f'` to any argument should evaluate to `Int 1`; in the second case, it should evaluate to the same function closure that `Variable 'f'` evaluates to. We'll keep track of which way a variable was bound by expanding our `bound_value` type:
 
        type expressed_value = Int of int | Bool of bool | Closure of char * term * assignment
        and bound_value = Nonrecursive of expressed_value |
@@ -253,7 +253,7 @@ In the first case, an application of `f` to any argument should evaluate to `Int
        and assignment = (char * bound_value) list;;
 
 
-Since we're not permitting ourselves OCaml's ability to recursively define cyclical lists, we're not going to be able to update the saved assignment in a closure when that closure is recursively bound to a variable. Instead, we'll just make a note of what variable `f` is supposed to be the recursively bound one---by binding it not to `Nonrecursive (Closure (arg_var, body, savedg))` but rather to `Recursive_Closure ('f', arg_var, body, savedg)`. We'll do the work to make the saved assignment recursive in the right way *later*, when we *evaluate* `f`. The result will look like this:
+Since we're not permitting ourselves OCaml's ability to recursively define cyclical lists, we're not going to be able to update the saved assignment in a closure when that closure is recursively bound to a variable. Instead, we'll just make a note that variable `'f'` is supposed to be the recursively bound one---by binding it not to `Nonrecursive (Closure (arg_var, body, savedg))` but rather to `Recursive_Closure ('f', arg_var, body, savedg)`. We'll do the work to make the saved assignment recursive in the right way *later*, when we *evaluate* `Variable 'f'`. The result will look like this:
 
        let rec eval (t : term) (g: assignment) = match t with
        ...