[B] let x be 1 + 2 in
let y be 10 in
- (x + y, x + 20) ==> (13, 23)
+ (x + y, x + 20)
+ ; evaluates to (13, 23)
In fragment [B], we bound the variables `x` and `y` to `int`s. We can also bind variables to function values, as here:
[C] let f be (lambda (x, y) -> x + y + 1) in
(f (10, 2), f (20, 2))
- ==> (13, 23)
+ ; evaluates to (13, 23)
If the expression that evaluates to a function value has a free variable in it, like `y` in the next fragment, it's interpreted as bound to whatever value `y` has in the surrounding lexical context:
[D] let y be 3 in
let f be (lambda (x) -> x + y) in
(f (10), f (20))
- ==> (13, 23)
+ ; evaluates to (13, 23)
Other choices about how to interpret free variables are also possible (you can read about "lexical scope" versus "dynamic scope"), but what we do here is the norm in functional programming languages, and seems to be easiest for programmers to reason about.
[E] let x be 4 in
let x be 3 in
- (x + 10, x + 20) ==> (13, 23)
+ (x + 10, x + 20)
+ ; evaluates to (13, 23)
As you can see, the narrowest assignment is what's effective. This is just like in predicate logic: consider <code>∃x (Fx and ∃x Gx)</code>. The computer-science terminology to describe this is that the narrower assignment of `x` to the value 3 **shadows** the wider assignment to 4.
x + y
) in
; here the assignment of 3 to y has expired
- (f (10), y, f (20)) ==> (13, 2, 23)
+ (f (10), y, f (20))
+ ; evaluates to (13, 2, 23)
OK, now we're ready for our main event, **mutable variables.** We'll introduce new syntax to express an operation where we're not shadowing a wider assignment, but *changing* the original assignemnt:
; here the change in what value y was assigned *sticks*
; because we *updated* the value of the original variable y
; instead of introducing a new y with a narrower scope
- (f (10), y, f (19)) ==> (13, 3, 23)
+ (f (10), y, f (19))
+ ; evaluates to (13, 3, 23)
In languages that have native syntax for this, there are two styles in which it can be expressed. The *implicit style* is exemplified in fragment [G] above, and also in languages like C: