X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=test2.mdwn;h=dcc8a1a73c32f3f5fd4fc38c97f2c89be6f65578;hp=138ee500af5bc53bd4abae5de0eb80ebce958a86;hb=46354da45e90d803a324be20b6613a8700349a1c;hpb=84c6bcbe5d95c8fe3d272a1d4ebd02dedee8b87c diff --git a/test2.mdwn b/test2.mdwn index 138ee500..dcc8a1a7 100644 --- a/test2.mdwn +++ b/test2.mdwn @@ -533,3 +533,148 @@ Here's how it looks to say the same thing in various of these languages. Read this several times until you understand it. +7. Functions can also be bound to variables (and hence, cease being "anonymous"). + + In Scheme: + + (let* [(bar (lambda (x) B))] M) + + then wherever `bar` occurs in `M` (and isn't rebound by a more local "let" or "lambda"), it will be interpreted as the function `(lambda (x) B)`. + + Similarly, in OCaml: + + let bar = fun x -> B in + M + + This in Scheme: + + (let* [(bar (lambda (x) B))] (bar A)) + + as we've said, means the same as: + + ((lambda (bar) (bar A)) (lambda (x) B)) + + which, as we'll see, is equivalent to: + + ((lambda (x) B) A) + + and that means the same as: + + (let* [(x A)] B) + + in other words: evaluate `B` with `x` assigned to the value `A`. + + Similarly, this in OCaml: + + let bar = fun x -> B in + bar A + + is equivalent to: + + (fun x -> B) A + + and that means the same as: + + let x = A in + B + +8. Pushing a "let"-binding from now until the end + + What if you want to do something like this, in Scheme? + + (let* [(x A)] ... for the rest of the file or interactive session ...) + + or this, in OCaml: + + let x = A in + ... for the rest of the file or interactive session ... + + Scheme and OCaml have syntactic shorthands for doing this. In Scheme it's written like this: + + (define x A) + ... rest of the file or interactive session ... + + In OCaml it's written like this: + + let x = A;; + ... rest of the file or interactive session ... + + It's easy to be lulled into thinking this is a kind of imperative construction. *But it's not!* It's really just a shorthand for the compound "let"-expressions we've already been looking at, taking the maximum syntactically permissible scope. (Compare the "dot" convention in the lambda calculus, discussed above.) + + +9. Some shorthand + + OCaml permits you to abbreviate: + + let bar = fun x -> B in + M + + as: + + let bar x = B in + M + + It also permits you to abbreviate: + + let bar = fun x -> B;; + + as: + + let bar x = B;; + + Similarly, Scheme permits you to abbreviate: + + (define bar (lambda (x) B)) + + as: + + (define (bar x) B) + + and this is the form you'll most often see Scheme definitions written in. + + However, conceptually you should think backwards through the abbreviations and equivalences we've just presented. + + (define (bar x) B) + + just means: + + (define bar (lambda (x) B)) + + which just means: + + (let* [(bar (lambda (x) B))] ... rest of the file or interactive session ...) + + which just means: + + (lambda (bar) ... rest of the file or interactive session ...) (lambda (x) B) + + or in other words, interpret the rest of the file or interactive session with `bar` assigned the function `(lambda (x) B)`. + + +10. Shadowing + + You can override a binding with a more inner binding to the same variable. For instance the following expression in OCaml: + + let x = 3 in + let x = 2 in + x + + will evaluate to 2, not to 3. It's easy to be lulled into thinking this is the same as what happens when we say in C: + + int x = 3; + x = 2; + + but it's not the same! In the latter case we have mutation, in the former case we don't. You will learn to recognize the difference as we proceed. + + The OCaml expression just means: + + (fun x -> ((fun x -> x) 2) 3) + + and there's no more mutation going on there than there is in: + +
+	∀x. (F x or ∀x (not (F x)))
+	
+ + When a previously-bound variable is rebound in the way we see here, that's called **shadowing**: the outer binding is shadowed during the scope of the inner binding. +