X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=week9.mdwn;h=dac311cb89dd3763ff28c812a73b4ed41dbe3b40;hp=a7b3278f476fbc3c1b30f3fc6406710291e874d7;hb=5d3d0a72ea4e8f1d23816d851fed8027ce768864;hpb=e4165e16984feee9c962872ac9319ce5c4b109c2 diff --git a/week9.mdwn b/week9.mdwn index a7b3278f..dac311cb 100644 --- a/week9.mdwn +++ b/week9.mdwn @@ -100,7 +100,13 @@ Scheme is similar. There are various sorts of reference cells available in Schem (set-box! ycell 3) (+ x (unbox ycell))) -(C has explicit-style mutable variables, too, which it calls *pointers*. But simple variables in C are already mutable, in the implicit style.) +C has explicit-style mutable variables, too, which it calls *pointers*. But simple variables in C are already mutable, in the implicit style. Scheme also has both styles of mutation. In addition to the explicit boxes, Scheme also lets you mutate unboxed variables: + + (begin + (define x 1) + (set! x 2) + x) + ; evaluates to 2 When dealing with explicit-style mutation, there's a difference between the types and values of `ycell` and `!ycell` (or in Scheme, `(unbox ycell)`). The former has the type `int ref`: the variable `ycell` is assigned a reference cell that contains an `int`. The latter has the type `int`, and has whatever value is now stored in the relevant reference cell. In an implicit-style framework though, we only have the resources to refer to the contents of the relevant reference cell. `y` in fragment [G] or the C snippet above has the type `int`, and only ever evaluates to `int` values. @@ -320,7 +326,7 @@ Similarly: Let's consider how to interpet our new syntactic forms `newref`, `deref`, and `setref`: -1. \[[newref starting_val]] should allocate a new reference cell in the store and insert `starting_val` into that cell. It should return some "key" or "index" or "pointer" to the newly created reference cell, so that we can do things like: +1. When `expr` evaluates to `starting_val`, **newref expr** should allocate a new reference cell in the store and insert `starting_val` into that cell. It should return some "key" or "index" or "pointer" to the newly created reference cell, so that we can do things like: let ycell = newref 1 in ... @@ -345,7 +351,7 @@ Let's consider how to interpet our new syntactic forms `newref`, `deref`, and `s in (Index new_index, s'') ... -2. When `expr` evaluates to a `store_index`, then `deref expr` should evaluate to whatever value is at that index in the current store. (If `expr` evaluates to a value of another type, `deref expr` is undefined.) In this operation, we don't change the store at all; we're just reading from it. So we'll return the same store back unchanged (assuming it wasn't changed during the evaluation of `expr`). +2. When `expr` evaluates to a `store_index`, then **deref expr** should evaluate to whatever value is at that index in the current store. (If `expr` evaluates to a value of another type, `deref expr` is undefined.) In this operation, we don't change the store at all; we're just reading from it. So we'll return the same store back unchanged (assuming it wasn't changed during the evaluation of `expr`). let rec eval expression g s = match expression with @@ -356,7 +362,7 @@ Let's consider how to interpet our new syntactic forms `newref`, `deref`, and `s in (List.nth s' n, s') ... -3. When `expr1` evaluates to a `store_index` and `expr2` evaluates to an `int`, then `setref expr1 expr2` should have the effect of changing the store so that the reference cell at that index now contains that `int`. We have to make a decision about what value the `setref ...` call should itself evaluate to; OCaml makes this `()` but other choices are also possible. Here I'll just suppose we've got some appropriate value in the variable `dummy`. +3. When `expr1` evaluates to a `store_index` and `expr2` evaluates to an `int`, then **setref expr1 expr2** should have the effect of changing the store so that the reference cell at that index now contains that `int`. We have to make a decision about what value the `setref ...` call should itself evaluate to; OCaml makes this `()` but other choices are also possible. Here I'll just suppose we've got some appropriate value in the variable `dummy`. let rec eval expression g s = match expression with @@ -669,7 +675,7 @@ Programming languages tend to provide a bunch of mutation-related capabilities a in let (adder', setter') = factory 1 in ... - Of course, in most languages you wouldn't be able to evaluate a comparison like `getter = getter'`, because in general the question whether two computations always return the same values for the same argument is not decidable. So typically languages don't even try to answer that question. However, it would still be true that `getter` and `getter'` (and `adder` and `adder'`) were extensionally equivalent. + Of course, in most languages you wouldn't be able to evaluate a comparison like `getter = getter'`, because in general the question whether two functions always return the same values for the same arguments is not decidable. So typically languages don't even try to answer that question. However, it would still be true that `getter` and `getter'` (and `adder` and `adder'`) were extensionally equivalent. However, they're not numerically identical, because by calling `setter 2` (but not calling `setter' 2`) we can mutate the function value `getter` (and `adder`) so that it's *no longer* qualitatively indiscernible from `getter'` (or `adder'`).