-Here's how to implement these. We'll suppose that our assignment function is list of pairs, as above and as in [week7](/reader_monad_for_variable_binding).
-
- let rec eval expression g s =
- match expression with
- ...
- | Var (c : char) ->
- let index = List.assoc c g
- (* retrieve the value at that index in the current store *)
- in let value = List.nth s index
- in (value, s)
-
- | Let ((c : char), expr1, expr2) ->
- let (starting_val, s') = eval expr1 g s
- (* get next free index in s' *)
- in let new_index = List.length s'
- (* insert starting_val there *)
- in let s'' = List.append s' [starting_val]
- (* evaluate expr2 using a new assignment function and store *)
- in eval expr2 ((c, new_index) :: g) s''
-
- | Change ((c : char), expr1, expr2) ->
- let (new_value, s') = eval expr1 g s
- (* lookup which index is associated with Var c *)
- in let index = List.assoc c g
- (* now we create a list which is just like s' except it has new_value at index *)
- in let rec replace_nth lst m =
- match lst with
- | [] -> failwith "list too short"
- | x::xs when m = 0 -> new_value :: xs
- | x::xs -> x :: replace_nth xs (m - 1)
- in let s'' = replace_nth s' index
- (* evaluate expr2 using original assignment function and new store *)
- in eval expr2 g s''
-
-Note: Chris uses this kind of machinery on the third page of the Nov 22 handout. Except he implements `Let` the way we here implement `Change`. And he adds an implementation of `Alias` (see below). Some minor differences: on his handout (and following Groenendijk, Stokhof and Veltman), he uses `r` and `g` where we use `g` and `s` respectively. Also, he implements his `r` with a function from `char` to `int`, instead of a `(char * int) list`, as we do here. It should be obvious how to translate between these. His implementation requires that variables always already have an associated peg. So that when we call `Let(c, expr1, expr2)` for the first time with `c`, there's a peg whose value is to be updated. That's easier to ensure when you implement the assignment as a function than as a `(char * int) list`.
+Here's how to implement these. We'll suppose that our assignment function is list of pairs, as above and as in [week7](/reader_monad_for_variable_binding). LINK
+
+ let rec eval expression e s =
+ match expression with
+ ...
+ | Var (var : identifier) ->
+ let index = List.assoc var e in
+ (* retrieve the value at that index in the current store *)
+ let res = List.nth s index in
+ (res, s)
+
+ | Let ((var : identifier), expr1, expr2) ->
+ let (starting_val, s') = eval expr1 e s in
+ (* get next free index in s' *)
+ let new_index = List.length s' in
+ (* insert starting_val there *)
+ let s'' = List.append s' [starting_val] in
+ (* evaluate expr2 using a new assignment function and store *)
+ eval expr2 ((var, new_index) :: e) s''
+
+ | Change ((var : identifier), expr1, expr2) ->
+ let (new_value, s') = eval expr1 e s in
+ (* lookup which index is associated with Var var *)
+ let index = List.assoc var e in
+ (* now we create a list which is just like s' except it has new_value at index *)
+ let rec replace_nth lst m = match lst with
+ | [] -> failwith "list too short"
+ | x::xs when m = 0 -> new_value :: xs
+ | x::xs -> x :: replace_nth xs (m - 1) in
+ let s'' = replace_nth s' index in
+ (* evaluate expr2 using original assignment function and new store *)
+ eval expr2 e s''
+
+Note: Chris uses this kind of machinery on the third page of the Nov 22 handout. Except he implements `Let` the way we here implement `Change`. And he adds an implementation of `Alias` (see below). Some minor differences: on his handout (and following Groenendijk, Stokhof and Veltman), he uses `r` and `e` where we use `e` and `s` respectively. Also, he implements his `r` with a function from `identifier` to `int`, instead of a `(identifier * int) list`, as we do here. It should be obvious how to translate between these. His implementation requires that variables always already have an associated peg. So that when we call `Let(var, expr1, expr2)` for the first time with `var`, there's a peg whose value is to be updated. That's easier to ensure when you implement the assignment as a function than as a `(identifier * int) list`.