next chunk of edits
authorjim <jim@web>
Fri, 6 Feb 2015 10:47:09 +0000 (05:47 -0500)
committerLinux User <ikiwiki@localhost.members.linode.com>
Fri, 6 Feb 2015 10:47:09 +0000 (05:47 -0500)
rosetta1.mdwn

index 4576a9b..d1fd7ef 100644 (file)
@@ -11,6 +11,9 @@ Also, if you want to read code written outside this class, or have others read y
 
 We hope, though, that learning Kapulet first puts you in a position to make that shift more effortlessly, and also to more quickly see the places where there's underlying unity to Scheme, OCaml, and Haskell, despite their diverse syntaxes. (And idiosyncratic warts.)
 
 
 We hope, though, that learning Kapulet first puts you in a position to make that shift more effortlessly, and also to more quickly see the places where there's underlying unity to Scheme, OCaml, and Haskell, despite their diverse syntaxes. (And idiosyncratic warts.)
 
+
+
+
 ### Comments
 
     ...  # this is a comment in Kapulet, that goes until the end of the line
 ### Comments
 
     ...  # this is a comment in Kapulet, that goes until the end of the line
@@ -35,7 +38,8 @@ Haskell also has block comments, though it `{- writes them differently -}`.
 Haskell's block comments also nest.
 
 Racket and Scheme also have block comments, though they `#| write them differently |#`.
 Haskell's block comments also nest.
 
 Racket and Scheme also have block comments, though they `#| write them differently |#`.
-These block comments also nest. Another form of block comments is `#;( ... )`. Those may contain nested parentheses, and extend until the next *matching* `)`. So prefixing `#;` to a complex parenthesized expression is a way to turn the whole thing into a comment. (These two comment styles aren't part of the official Scheme standard, but they are widely implemented.)
+These block comments also nest. Another form of block comments is `#;( ... )`. Those may contain nested parentheses, and extend until the next *matching* `)`. So prefixing `#;` to a complex parenthesized expression is a way to turn the whole thing into a comment. (These two comment styles only recently became part of the official Scheme standard, but they have been widely implemented.)
+
 
 
 
 
 
 
@@ -49,6 +53,35 @@ In OCaml and Kapulet, some variables made of letters also have infix syntax, suc
 
 
 
 
 
 
+
+### Equality and Booleans
+
+The relation that's written `==` in Kapulet is also written that way in Haskell. That symbol means something else in OCaml, having to do with mutable reference cells; to get the same notion in OCaml one writes just a single `=`. The negation of this relation is written `!=` in Kapulet, `/=` in Haskell, and `<>` in OCaml. (Again, `!=` means something else in OCaml.)
+
+FIXME 3 and Scheme Equalities
+
+The relations that are written `and`, `or`, and `not` in Kapulet are written the same way in Scheme. Note that in Scheme the first two can take zero or more arguments:
+
+    ; Scheme
+    (and)
+    (and bool1)
+    (and bool1 bool2)
+    (and bool1 bool2 bool3)
+
+As you'd expect `(and bool1)` evaluates the same as plain `bool1`; similarly with `(or bool1)`. What do you think `(and)` with no arguments should evaluate to? How about `(or)`?
+
+These relations are written in Haskell and OCaml as `&&`, `||`, and `not`. (Haskell uses `and` and `or` to express other functions, which compute the joint conjunction or disjunction of every `Bool` value in a List of such. OCaml permits `or` as an old synonym for `||`, but discourages using that spelling. OCaml also permits `&` as an old, discouraged synonym for `&&`.)
+
+The values that are written `'true` and `'false` in Kapulet are written in Haskell as `True` and `False`, and in OCaml as just `true` and `false`. (It'd be more consistent with OCaml's other naming policies for them to have said True and False, but they didn't.) These are written `#t` and `#f` in Scheme, but in Scheme in many contexts any value that isn't `#f` will behave as though it were `#t`, even values you might think are more "false-like", like `0` and the empty list.
+<a id=truth-like></a> Thus `(if 0 'zero 'nope)` will evaluate to `'zero`.
+
+Some Scheme implementations, such as Racket, permit `#true` and `#false` as synonyms for `#t` and `#f`.
+
+Scheme also recognizes the values `'true` and `'false`, but it treats `'false` as distinct from `#f`, and thus as a "truth-like" value, like all of its other values that aren't `#f`. Kapulet essentially took Scheme's `boolean` values and collapsed them into being a subtype of its `symbol` values. FIXME also with chars.
+
+
+
+
 ### Infix operators and parentheses
 
 
 ### Infix operators and parentheses
 
 
@@ -60,15 +93,16 @@ not:
 
     + 1 2
 
 
     + 1 2
 
-Although all three of these languages permits you to enclose an infix operator in parentheses to make a *section*, which no longer has infix syntax. In Kapulet, `( + )` is the same as &lambda; `(x, y). x + y`, whereas in OCaml and Haskell it's a *curried* function, which we can write (in Kapulet syntax) as &lambda; `x y. x + y`. We'll discuss sections and curried functions below.
+<a id=pre-curried></a>
+But all three of these languages permits you to enclose an infix operator in parentheses to make a *section*, which no longer has infix syntax. In Kapulet, `( + )` is the same as &lambda; `(x, y). x + y`, whereas in OCaml and Haskell it's a *curried* function, which we can write (in Kapulet syntax) as &lambda; `x y. x + y`. We'll discuss [[sections|#sections]] and [[curried functions|#curried]] below.
 
 
-Kapulet and OCaml have some operators spelled with letters also taking infix syntax, such as `comp` in Kapulet or `mod` in OCaml. In Haskell, this is never the case: variables that are made of letters are only treated as function terms being applied to arguments *when they're at the start* of a list of expressions; and variables that are made of punctuation symbols, and not enclosed in parentheses, will only be treated as infix operators. However, Haskell permits you to temporarily "flag" a  function term made of letters to behave like an infix operator, by enclosing it in `` ` `` marks. Thus in Haskell you can write:
+Kapulet and OCaml have some variables made of (or spelled with) letters also taking infix syntax, such as `comp` in Kapulet or `mod` in OCaml. In Haskell, this is never the case: variables that are made of letters are only treated as function terms being applied to arguments *when they're at the start* of a list of expressions; and variables that are made of punctuation symbols, and not enclosed in parentheses, will only be treated as infix operators. However, Haskell permits you to temporarily "flag" a  function term made of letters to behave like an infix operator, by enclosing it in `` ` `` marks. Thus in Haskell you can write:
 
     3 `mod` 2
 
 But without the `` ` ``, you'd have to write: `mod 3 2`.
 
 
     3 `mod` 2
 
 But without the `` ` ``, you'd have to write: `mod 3 2`.
 
-Scheme has no infix operators. It ruthlessly demands that all functions to be applied to arguments come at the start of a list of expressions, regardless of whether those functions are spelled using letters, punctuation symbols, or a mix of the two. Thus in Scheme one always writes:
+Scheme has no infix operators. It ruthlessly demands that all functions to be applied to arguments come at the start of a list of expressions, regardless of whether the functions are specified by variables made of letters, punctuation symbols, or a mix of the two, or even if the functions are computed by evaluating more complex expressions. Thus in Scheme one always writes:
 
     (+ 3 2)
 
 
     (+ 3 2)
 
@@ -76,17 +110,17 @@ and the like. Moreover, in Scheme parentheses are never optional and never redun
 
     ((+) 3 2)
 
 
     ((+) 3 2)
 
-what that would mean is that `+` is first being applied to *zero* arguments, which is different from not applying it all. (In Kapulet, OCaml, and Haskell, one would write that `f` is being applied to "zero arguments" like this: `f ()`. FIXME) Scheme helpfully defines the result of applying `+` to zero arguments to be `0`. So `((+) 3 2)` would evaluate to whatever `(0 3 2)` does, and that's an error, because `0` is not a function.
+what that would mean is that `+` is first being applied to *zero* arguments, which is different from not applying it all. (In Kapulet, OCaml, and Haskell, one would write that `f` is being applied to "zero arguments" like this: `f ()`. We will discuss FIXME) Scheme helpfully defines the result of applying `+` to zero arguments to be `0`. So `((+) 3 2)` would evaluate to whatever `(0 3 2)` does, and that's an error, because `0` is not a function.
 
 
-Note that `(0 3 2)`, although it *is*, qua expression, a list of numbers, does not evaluate to a list. To get an expression that *evaluates to* that list, you'd have to use `(list 0 3 2)` or `'(0 3 2)`. (Notice the initial `'`.) FIXME
+Note that `(0 3 2)`, although it *is*, qua expression, a list of numbers, does not evaluate to a list. To get an expression that *evaluates to* that list, you'd have to use `(list 0 3 2)` or `'(0 3 2)`. (Notice the initial `'`.) More on this [[below|#writing-scheme-lists]].
 
 In Scheme, you can also write `(+ 3 2 10)`, and so on. You only have to write `(+ (+ 3 2) 10)` if you really want to.
 
 
 In Scheme, you can also write `(+ 3 2 10)`, and so on. You only have to write `(+ (+ 3 2) 10)` if you really want to.
 
-Parentheses have many other roles in Scheme, as well; they're a ubiquitous part of the syntax, and don't always express function application. You might sometimes feel they are overused.
-
-You may sometimes see `[ ... ]` being used instead of `( ... )`. This is just a stylistic variant, they work exactly the same. The official Scheme standard doesn't permit that, but most Scheme implementations do. It can help keep track of which closing `]` or `)` goes with which opening `[` or `)`. The opening and closing symbols always have to correspond.
+Parentheses have many other roles in Scheme, too; they're a ubiquitous part of the syntax, and don't always express function application. You might sometimes feel they are overused.
 
 
+You may sometimes see `[ ... ]` being used in Scheme, instead of `( ... )`. This is just a stylistic variant; they work exactly the same. The official Scheme standard doesn't permit this usage, but most Scheme implementations do. It can help keep track of which closing `]` or `)` goes with which opening `[` or `(`. The opening and closing symbols always have to correspond.
 
 
+<a id=curried></a>
 In Scheme, the default style for defining functions is as taking several arguments simultaneously, that is the *uncurried* style. In OCaml and Haskell, the default style is to define them *curried*. Curried functions can easily be partially applied:
 
     (* OCaml *)
 In Scheme, the default style for defining functions is as taking several arguments simultaneously, that is the *uncurried* style. In OCaml and Haskell, the default style is to define them *curried*. Curried functions can easily be partially applied:
 
     (* OCaml *)
@@ -97,11 +131,11 @@ In Scheme, the default style for defining functions is as taking several argumen
 
 will result in `5`.
 
 
 will result in `5`.
 
-In Scheme, the default would be to define `add` like this:
+In Scheme, the common idiom would be to define `add` like this:
 
     (define add (lambda (x y) (+ x y)))
 
 
     (define add (lambda (x y) (+ x y)))
 
-Then you cannot say `(add 2)`, because `add` will be expecting two arguments, but you only supplied one. You can however define curried functions in Scheme, it's just more laborious:
+(We'll explain `define` [[below#define]].) After this, you cannot say `(add 2)`, because `add` will be expecting two arguments, but you only supplied one. You can however define curried functions in Scheme, it's just more laborious:
 
     (define curried_add (lambda (x) (lambda (y) (+ x y))))
     (define add2 (curried_add 2))
 
     (define curried_add (lambda (x) (lambda (y) (+ x y))))
     (define add2 (curried_add 2))
@@ -112,14 +146,15 @@ will result in `5`. This is the best one can do in official Scheme, but there ar
 OCaml and Haskell also permit defining functions in uncurried form:
 
     (* OCaml *)
 OCaml and Haskell also permit defining functions in uncurried form:
 
     (* OCaml *)
-    let add  = fun (x, y) -> x + y in
+    let add  = fun (x, y) -> x + y (* uncurried*) in
     let add2 = fun add 2 in ...
 
 Here the last displayed line will fail, because `add` expects as its argument a tuple of two numbers.
 
     let add2 = fun add 2 in ...
 
 Here the last displayed line will fail, because `add` expects as its argument a tuple of two numbers.
 
-Kapulet essentially works like OCaml and Haskell; though for pedagogical reasons I started out by introducing uncurried definitions, rather than the *curried* definitions those other languages predominantly use.
+Kapulet essentially works like OCaml and Haskell; though for pedagogical reasons we started out by introducing uncurried definitions, rather than the *curried* definitions those other languages predominantly use.
 
 
-[[As we mentioned|topics/week1_advanced_notes#sections]], in Kapulet, OCaml, and Haskell, there is a shorthand that enables you to write things like:
+<a id=sections></a>
+[[As we mentioned in the course notes|topics/week1_advanced_notes#sections]], in Kapulet, OCaml, and Haskell, there is a shorthand that enables you to write things like:
 
     # Kapulet
     let
 
     # Kapulet
     let
@@ -137,9 +172,13 @@ like this:
       plus      match ( + )
     in (ten_minus, and_ys)
 
       plus      match ( + )
     in (ten_minus, and_ys)
 
-There are just minor differences between these languages. First, OCaml doesn't have the `( + 10)` or `(10 + )` forms, but only the `( + )`. Second, as a special case, OCaml doesn't permit you to do this with its list-consing operator `::`. You have to write `fun x xs -> x :: xs`, not `( :: )`. Whereas in Kapulet `( & )`, `(x & )`, and `( & xs)` are all sections using its sequence-consing operator `&`; and in Haskell, `( : )`, `(x : )`, and `( : xs)` are the same.
+There are just minor differences between these languages. First, OCaml doesn't have the `( + 10)` or `(10 + )` forms, but only the `( + )`.
+
+Second, as a special case, OCaml doesn't permit you to do this with its list cons-ing operator `::`. You have to write `fun x xs -> x :: xs`, not `( :: )`. Whereas in Kapulet `( & )`, `(x & )`, and `( & xs)` are all sections using its sequence cons-ing operator `&`; and in Haskell, `( : )`, `(x : )`, and `( : xs)` are the same.
 
 
-Thirdly, in Kapulet, `( - 10)` also expresses &lambda; `x. x - 10` (consistently with `(10 - )`), but Haskell (and OCaml) treat this form differently, and interpret it as meaning the integer `- 10`. Here's how to express some things in Kapulet:
+Third, as [[mentioned above|#pre-curried]], OCaml's and Haskell's `( + )` and the like evaluate to *curried* functions.
+
+Fourth, in Kapulet, `( - 10)` expresses &lambda; `x. x - 10` (consistently with `(10 - )`), but Haskell (and OCaml) treat this specific form differently, and interpret it as meaning the integer `- 10`. Here's how to express some things in Kapulet:
 
     # Kapulet
     (0 - 2)
 
     # Kapulet
     (0 - 2)
@@ -148,40 +187,18 @@ Thirdly, in Kapulet, `( - 10)` also expresses &lambda; `x. x - 10` (consistently
     ( - ) (5, 3)
     
 
     ( - ) (5, 3)
     
 
-and here are their translations into Haskell:
+and here are their translations into natural Haskell:
 
     -- Haskell
 
     -- Haskell
-    ( -2 )
+    ( -2 )        -- (0 - 2) also works
     (subtract 2)  -- subtract 2 10 == 8
     negate        -- (0 - ) also works
     ( - ) 5 3
 
 OCaml expresses `(0 - )` or `negate` as `~-`. You can write `3 * (0 - 2)` in OCaml as either `3 * ( -2 )` or as `3 * ~-2`.
 
     (subtract 2)  -- subtract 2 10 == 8
     negate        -- (0 - ) also works
     ( - ) 5 3
 
 OCaml expresses `(0 - )` or `negate` as `~-`. You can write `3 * (0 - 2)` in OCaml as either `3 * ( -2 )` or as `3 * ~-2`.
 
-I know all these languages fairly well, and I still find this last issue difficult to keep track of. You may be starting to understand why I spoke of "warts."
-
-
-### Equality and Booleans
-
-The relation that's written `==` in Kapulet is also written that way in Haskell. That symbol means something else in OCaml, having to do with mutable reference cells; to get the same notion in OCaml one writes just a single `=`. The negation of this notion is written `!=` in Kapulet, `/=` in Haskell, and `<>` in OCaml. (Again, `!=` means something else in OCaml.)
+I know all these languages fairly well, and I still find this fourth issue difficult to keep track of. You may be starting to understand why I spoke of "warts."
 
 
-The relations that are written `and`, `or`, and `not` in Kapulet are written the same way in Scheme. Note that in Scheme the first two can take zero or more arguments:
-
-    ; Scheme
-    (and)
-    (and bool1)
-    (and bool1 bool2)
-    (and bool1 bool2 bool3)
-
-As you'd expect `(and bool1)` evaluates the same as plain `bool1`; similarly with `(or bool1)`. What do you think `(and)` with no arguments should evaluate to? How about `(or)`?
-
-These relations are written in Haskell and OCaml as `&&`, `||`, and `not`. (Haskell uses `and` and `or` to express functions that form the conjunction or disjunction of every `Bool` value in a List of such. OCaml permits `or` as an old synonym for `||`, but discourages using that spelling. OCaml also permits `&` as an old, discouraged synonym for `&&`.)
-
-The values that are written `'true` and `'false` in Kapulet are written in Haskell as `True` and `False`, and in OCaml as just `true` and `false`. They're written `#t` and `#f` in Scheme, but in Scheme in many contexts any value that isn't `#f` will behave as though it were `#t`, even values you might think are more "false-ish", like `0` and the empty list. Thus `(if 0 'yes 'no)` will evaluate to `'yes`.
-
-Some Scheme implementations, such as Racket, permit `#true` and `#false` as synonyms for `#t` and `#f`.
-
-Scheme also recognizes the values `'true` and `'false`, but it treats `'false` as distinct from `#f`, and thus as a "true-ish" value, like all of its other values that aren't `#f`. Kapulet essentially took Scheme's `boolean` values and collapsed them into being a subtype of its `symbol` values. FIXME also with chars.
 
 
 
 
 
 
@@ -195,7 +212,7 @@ can also be written:
 
     [1, 2, 3]
 
 
     [1, 2, 3]
 
-Haskell is very similar, except that it calls these Lists, and its cons-ing operator is written `:`. OCaml also calls them `list`s, and its cons-operator is written `::`. (OCaml *also* uses `:`, but it uses it to deal with types, and Haskell in turn also uses `::`, but that's what *it* uses to deal with types. Grr.)
+Haskell is very similar, except that it calls these Lists, and its cons-ing operator is written `:`. OCaml also calls them `list`s, and its cons-operator is written `::`. (OCaml *also* uses Haskell's symbol `:`, but it uses it to deal with types; and Haskell in turn also uses OCaml's symbol `::`, but that's what *it* uses to deal with types. Grr.)
 
 Kapulet writes the operator that concatenates or appends sequences as `&&`. Thus:
 
 
 Kapulet writes the operator that concatenates or appends sequences as `&&`. Thus:
 
@@ -213,7 +230,7 @@ evaluates to `"overdue"`. In OCaml, `string`s aren't implemented as `list`s, so
     [1; 2] @ [3; 4; 5] ;;
     "over" ^ "due" ;;
 
     [1; 2] @ [3; 4; 5] ;;
     "over" ^ "due" ;;
 
-evaluate to `[1; 2; 3; 4; 5]` and `"overdue"`. Note that OCaml separates its `list` items with semicolons not commas. If you write `[1, 2, 3]` in OCaml, it will think that's a one-element list whose first element is a triple, that is, what you'd write in Haskell as `[(1, 2, 3)]`.
+evaluate to `[1; 2; 3; 4; 5]` and `"overdue"`. Note that OCaml separates its `list` elements with semicolons not commas. If you write `[1, 2, 3]` in OCaml, it will think that's a one-element list whose first element is a triple, that is, what you'd write in Haskell as `[(1, 2, 3)]`.
 
 Here are some list functions in Kapulet:
 
 
 Here are some list functions in Kapulet:
 
@@ -238,8 +255,8 @@ Here are some list functions in Kapulet:
     join         # converts [[10, 20], [30], [], [40, 50]]
                  # to [10, 20, 30, 40, 50] (but only "joining" a single layer of []s)
     (mem)        # infix syntax, 2 mem [1, 2, 3] == 'true
     join         # converts [[10, 20], [30], [], [40, 50]]
                  # to [10, 20, 30, 40, 50] (but only "joining" a single layer of []s)
     (mem)        # infix syntax, 2 mem [1, 2, 3] == 'true
-    nth          # nth [10, 20, 30] 1 == 20, because the first element
-                 # is at position 0; fails if index is out of bounds
+    nth          # nth [10, 20, 30] 1 == 20, because 10 occupies position 0
+                 # fails if the index is out of bounds
     all? p xs    # all? odd? [1, 3, 5] == 'true
     any? p xs    # any? even? [1, 3, 5] == 'false
 
     all? p xs    # all? odd? [1, 3, 5] == 'true
     any? p xs    # any? even? [1, 3, 5] == 'false
 
@@ -258,7 +275,7 @@ Here are the corresponding functions in Haskell:
     filter
     Data.List.partition
     map
     filter
     Data.List.partition
     map
-    zipWith  {- zip handles the special case where f is the function that forms ordered pairs
+    zipWith  {- zip handles the special case of zipWith where f is the function that forms ordered pairs
                 both zipWith and zip stop with the shortest list -}
     unzip    {- unlike unmap2, doesn't take an explicit f argument
                 just assumes it's (\(x, y) -> (x, y)) -}
                 both zipWith and zip stop with the shortest list -}
     unzip    {- unlike unmap2, doesn't take an explicit f argument
                 just assumes it's (\(x, y) -> (x, y)) -}
@@ -267,7 +284,8 @@ Here are the corresponding functions in Haskell:
     reverse
     concat   -- corresponding to join
     elem     -- not infix syntax, but often written as: 2 `elem` [1, 2, 3]
     reverse
     concat   -- corresponding to join
     elem     -- not infix syntax, but often written as: 2 `elem` [1, 2, 3]
-    (!!)     -- infix syntax: [10, 20, 30] !! 1 == 20; fails if index is out of bounds
+    (!!)     -- infix syntax: [10, 20, 30] !! 1 == 20
+             -- fails if the index is out of bounds
     all p xs
     any p xs
 
     all p xs
     any p xs
 
@@ -275,7 +293,7 @@ Here are the corresponding functions in Haskell:
 
 Here they are in OCaml:
 
 
 Here they are in OCaml:
 
-    length
+    List.length
     (@)          (* or List.append *)
     (* no function corresponding to empty? *)
     List.tl      (* compare List.hd, which fails on [] *)
     (@)          (* or List.append *)
     (* no function corresponding to empty? *)
     List.tl      (* compare List.hd, which fails on [] *)
@@ -291,19 +309,21 @@ Here they are in OCaml:
     List.rev
     List.concat  (* also List.flatten, which still only "joins" a single layer of []s *)
     List.mem     (* not infix syntax *)
     List.rev
     List.concat  (* also List.flatten, which still only "joins" a single layer of []s *)
     List.mem     (* not infix syntax *)
-    List.nth     (* List.nth [10; 20; 30] 1 = 20; fails if index is out of bounds *)
+    List.nth     (* List.nth [10; 20; 30] 1 = 20; fails if the index is out of bounds *)
     List.for_all p xs
     List.exists p xs
 
 
     List.for_all p xs
     List.exists p xs
 
 
-How does all this look in Scheme? Well, Scheme has a notion they call a (proper) `list`, and also a notion they call a `vector`. There are also what Scheme calls "improper" `list`s, with `(cons 1 'nonlist)` or `'(1 . nonlist)`, where `'nonlist` is any non-list (here it's a `symbol`) being a limiting case. Let's ignore the improper `list`s. Scheme's (proper) `list`s and `vector`s each has a claim to correspond to Kapulet's sequences, Haskell's Lists, and OCaml's `list`s. Each is also somewhat different. The dominant differences are:
+<a id=scheme-lists></a>
+How does all this look in Scheme? Well, Scheme has a notion they call a (proper) `list`, and also a notion they call a `vector`. There are also what Scheme calls "improper" `list`s, with `(cons 1 'nonlist)` or `'(1 . nonlist)`, where `'nonlist` is any non-list (here it's a `symbol`) being a limiting case. Let's ignore the improper `list`s. Scheme's (proper) `list`s and `vector`s each have a claim to correspond to Kapulet's sequences / Haskell's Lists / OCaml's `list`s. But they also differ from those. The main differences are:
 
 1.  these structures in Scheme can contain heterogenously-typed elements, including further `list`s and `vector`s in some positions but not in others
 2.  in the official Scheme standard, `list`s and `vector`s are both *mutable* containers, that is, one and the same persisting `list` structure can have different
 elements at different stages in a program's evaluation
 
 
 1.  these structures in Scheme can contain heterogenously-typed elements, including further `list`s and `vector`s in some positions but not in others
 2.  in the official Scheme standard, `list`s and `vector`s are both *mutable* containers, that is, one and the same persisting `list` structure can have different
 elements at different stages in a program's evaluation
 
-Many Scheme implementations also provide immutable versions of `list`s and `vector`s, more closely approximating the sequences/lists in Kapulet, Haskell, and OCaml. With some configurations, Racket even makes the immutable versions the defaults. But none of these are yet part of the official Scheme standard. Also, difference 1 is present in all Scheme implementations. This makes Scheme's `list`s and `vector`s in some ways more akin to *tuples* in the other languages (to "proper" tuples in Kapulet).
+Many Scheme implementations also provide immutable versions of `list`s and `vector`s, more closely approximating the sequences/lists in Kapulet, Haskell, and OCaml. With some configurations, Racket even makes the immutable versions the defaults. But none of these are yet part of the official Scheme standard. Also, difference 1 is present in all Scheme implementations. This makes Scheme's `list`s and `vector`s in some ways more akin to *tuples* in the other languages (to "proper" tuples in Kapulet) (see [[below|#tuples]]).
 
 
+<a id=writing-scheme-lists></a>
 There are also some differences in how `list`s are specified in Scheme versus the other languages. In Scheme, one writes the empty list like this:
 
     (list)
 There are also some differences in how `list`s are specified in Scheme versus the other languages. In Scheme, one writes the empty list like this:
 
     (list)
@@ -334,22 +354,47 @@ Here are the `list` functions in Scheme corresponding to the functions listed in
     null?             ; corresponds to Kapulet's empty?, Haskell's null
     car               ; corresponds to Haskell's head
     cdr               ; corresponds to Kapulet's and Haskell's tail
     null?             ; corresponds to Kapulet's empty?, Haskell's null
     car               ; corresponds to Haskell's head
     cdr               ; corresponds to Kapulet's and Haskell's tail
-    (list-tail xs k)  ; corresponds to Kapulet's drop (k, xs); fails if out-of-bounds
+    (list-tail xs k)  ; corresponds to Kapulet's drop (k, xs)
+                      ; fails if the list has length < k
     ; no official function corresponding to take or split or filter or partition
     map               ; corresponds to Kapulet's map and map2
                       ; can take one or more list arguments
     ; no official function corresponding to unmap2 or takewhile or dropwhile
     reverse
     ; no official function corresponding to join/concat
     ; no official function corresponding to take or split or filter or partition
     map               ; corresponds to Kapulet's map and map2
                       ; can take one or more list arguments
     ; no official function corresponding to unmap2 or takewhile or dropwhile
     reverse
     ; no official function corresponding to join/concat
-    member            ; corresponds to Kapulet's (mem) and Haskell's elem
+    member            ; corresponds to Kapulet's (mem) and Haskell's elem  FIXME: eqv? version
     (list-ref xs k)   ; corresponds to Kapulet's `nth xs k`
     (list-ref xs k)   ; corresponds to Kapulet's `nth xs k`
+                      ; fails if the index k is out of bounds
     ; no official function corresponding to all or any
 
 All of the functions listed as missing from the official Scheme standard can be found in various add-on libraries, or you could define them yourself if you had to.
 
     ; no official function corresponding to all or any
 
 All of the functions listed as missing from the official Scheme standard can be found in various add-on libraries, or you could define them yourself if you had to.
 
+<a id=tuples></a>
+FIXME tuples
+
+
 
 
+LATER
+### Other functions
 
 
-### Pattern-matching
+Same in all: `succ`, `pred`, `fst`, `snd`.
+
+Same in Kapulet and Haskell (modulo the differences between multivalues and tuples), aren't predefined in OCaml: `id`, `const`, `flip`, `curry`, `uncurry`.
+
+Kapulet's `(comp)` is Haskell's `( . )`; isn't predefined in OCaml.
+
+Kapulet and Haskell both have `( $ )`; OCaml expresses as `( @@ )`. (OCaml also has `|>` to express the converse operation: `f x`, `f @@ x` and `x |> f` all mean the same.)
+
+Kapulet's `odd?` and `even?` are Haskell's `odd`, `even`; aren't predefined in OCaml.
+
+Kapulet's `swap` (defined in homework) is Haskell's `Data.Tuple.swap`.
+
+Kapulet's `dup` isn't predefined in Haskell but can be easily expressed as `\x -> (x, x)`.
+
+
+
+
+### Case, Cond, and If ... then ...
 
 The complex expression that's written like this in Kapulet:
 
 
 The complex expression that's written like this in Kapulet:
 
@@ -369,6 +414,7 @@ is written very similarly in Haskell:
       x -> resultx
     }
 
       x -> resultx
     }
 
+<a id=haskell-whitespace></a>
 Unlike the other languages we're discussing, Haskell pays special attention to the whitespace/indentation of what you write. This permits you to omit the `{`, `;`, and `}`s in the above, if you've got the indentation right. And that's how you will often see Haskell code displayed. On this website, though, I propose to always include the `{`s and so on when displaying Haskell code, because the indentation rules aren't 100% intuitive. It's easy to read properly-indented Haskell code, but until you've learned and practiced the specific rules, it's not always easy to write it.
 
 This is written only a little bit differently in OCaml:
 Unlike the other languages we're discussing, Haskell pays special attention to the whitespace/indentation of what you write. This permits you to omit the `{`, `;`, and `}`s in the above, if you've got the indentation right. And that's how you will often see Haskell code displayed. On this website, though, I propose to always include the `{`s and so on when displaying Haskell code, because the indentation rules aren't 100% intuitive. It's easy to read properly-indented Haskell code, but until you've learned and practiced the specific rules, it's not always easy to write it.
 
 This is written only a little bit differently in OCaml:
@@ -396,6 +442,8 @@ The syntax for [[guards|topics/week1_advanced_notes#guards]] and [[as-patterns|t
       ((complex_pat) as var, pat4)  then result3
     end
 
       ((complex_pat) as var, pat4)  then result3
     end
 
+<a id=haskell-guards></a>
+
     -- Haskell
     case some_expression {
       pat1 | guard              -> result1;
     -- Haskell
     case some_expression {
       pat1 | guard              -> result1;
@@ -405,8 +453,8 @@ The syntax for [[guards|topics/week1_advanced_notes#guards]] and [[as-patterns|t
 
     (* OCaml *)
     match some_expression with
 
     (* OCaml *)
     match some_expression with
-      pat1   when guard             -> result0 |
-      pat1   when different_guard   -> result1 |
+      pat1   when guard             -> result1 |
+      pat1   when different_guard   -> result2 |
       ((complex_pat) as var, pat4   -> result3
 
 
       ((complex_pat) as var, pat4   -> result3
 
 
@@ -419,17 +467,17 @@ The official Scheme standard only provides for a limited version of this. There
       ((2 3 5) 'smallprime)
       (else 'toobig))
 
       ((2 3 5) 'smallprime)
       (else 'toobig))
 
-The results can be complex expressions; I just used bare symbols here for illustration. Note that the literal patterns in the first two clauses are surrounded by an extra pair of parentheses than you might expect. The reason is shown in the third clause, which begins `(2 3 5)`. This does not mean to match a list containing the values `2` `3` and `5`. Instead it means to match the simple value `2` *or* the simple value `3` *or* the simple value `5`. The final `else` clause is optional.
+The results can be complex expressions; I just used bare symbols here for illustration. Note that the literal patterns in the first two clauses are surrounded by an extra pair of parentheses than you might expect. The reason is shown in the third clause, which begins `(2 3 5)`. This does not mean to match a list containing the values `2` `3` and `5`. Instead it means to match the simple value `2` *or* the simple value `3` *or* the simple value `5`. The final `else` clause is optional. FIXME no match?
 
 
-The patterns here can be any literal value (what the Scheme standards call a "datum"). Numbers are permitted, as are boolean literals (`#t` and `#f`) and symbolic atoms (`'alpha` and the like, though inside a pattern position in a `case`-expression, you omit the initial `'`). You can also use the list literal `'()` (again, omit the initial `'` when writing it as a pattern). Some implementations of Scheme allow more complex list patterns, matching literal lists like `'(alpha 0 () #t)`; others don't.
+The patterns here can be any literal value (what the Scheme standards call a "datum"). Numbers are permitted, as are boolean literals (`#t` and `#f`) and symbolic atoms (`'alpha` and the like, though inside a pattern position in a `case`-construction, you omit the initial `'`). You can also use the list literal `'()` (again, omit the initial `'` when writing it as a pattern). Some implementations of Scheme allow more complex list patterns, matching literal lists like `'(alpha 0 () #t)`; others don't.
 
 
-There are various add-on libraries to Scheme that will permit you to pattern-match in more ambitious ways, approximating what you can do in Kapulet, OCaml, and Haskell. We will explain some of these later, after we've introduced you to the notion of *datatypes*.
+There are various add-on libraries to Scheme that will permit you to pattern-match in more ambitious ways, approximating what you can do in Kapulet, OCaml, and Haskell. We will explain some of these later in the course, after we've introduced you to the notion of *datatypes*.
 
 
-What programmers using standard Scheme tend to do instead is to use *predicates* that query the type and/or structure of an unknown value, and then take separate evaluation paths depending on the result. This can be done with an `if...then...else...` construction, or with Scheme's more general `cond` construction. In Scheme, these two are equivalent:
+What programmers using standard Scheme tend to do instead is to use *predicates* that query the type and/or structure of an unknown value, and then take separate evaluation paths depending on the result. This can be done with an `if ... then ... else ...` construction, or with Scheme's more general `cond` construction. In Scheme, these two are equivalent:
 
     ; Scheme
 
     ; Scheme
-    (if test1 'result1
-              (if test2 'result2
+    (if test1 'result1                    ; else what follows:
+              (if test2 'result2          ; else what follows:
                         (if test3 'result3 'somethingelse)))
 
     (cond
                         (if test3 'result3 'somethingelse)))
 
     (cond
@@ -438,7 +486,9 @@ What programmers using standard Scheme tend to do instead is to use *predicates*
       (test3 'result3)
       (else  'somethingelse))
 
       (test3 'result3)
       (else  'somethingelse))
 
-The tests tend to use predicates like `null?` (are you the empty list?), `pair?` (are you a non-empty list, whether proper or improper?), `list?` (are you a proper list, whether empty or not?), `symbol?`, `boolean?`, `number?`, `zero?` (you get the idea). But you can also use more complex tests you write on the spot, or use antecedently-defined functions:
+The tests tend to use predicates like `null?` (are you the empty list?), `pair?` (are you a non-empty list, whether proper or improper?), `list?` (are you a proper list, whether empty or not?), `symbol?`, `boolean?`, `number?`, `zero?` (you get the idea). The *Little Schemer* books use their own predicates they call `atom?` (are you a non-list?) and `lat?` (are you a list all of whose members are atoms?)
+
+You can also use more complex tests you write on the spot, or your own antecedently-defined functions:
 
     ; Scheme...in case the parens left any doubt
     (define smallprime? (lambda (x) (if (= x 2) #t (if (= x 3) #t (if (= x 5) #t #f)))))
 
     ; Scheme...in case the parens left any doubt
     (define smallprime? (lambda (x) (if (= x 2) #t (if (= x 3) #t (if (= x 5) #t #f)))))
@@ -449,7 +499,7 @@ The tests tend to use predicates like `null?` (are you the empty list?), `pair?`
       ((and (> x 10) (< x 20)) 'teenaged)
       (else 'unknown))
 
       ((and (> x 10) (< x 20)) 'teenaged)
       (else 'unknown))
 
-Remember that in Scheme, an expression doesn't have to evaluate to `#t` to be treated as "truth-like". *Every* value other than `#f` is treated as truth-like. So `(if 0 'zero 'nope)` evaluates to `'zero`.
+Remember that in Scheme, an expression doesn't have to evaluate to `#t` to be treated as "truth-like". *Every* value other than `#f` is treated as truth-like. As I [[said before|#truth-like]] `(if 0 'zero 'nope)` evaluates to `'zero`.
 
 You may sometimes see Scheme `cond` constructions written with this kind of clause:
 
 
 You may sometimes see Scheme `cond` constructions written with this kind of clause:
 
@@ -477,19 +527,20 @@ Scheme standards after r5rs also provide two further conditional constructions,
     (unless test-expression
        result-expression2...)
 
     (unless test-expression
        result-expression2...)
 
-If the test-expression evaluates to `#f`, then the `when` expression evaluates to a special "void" value; mutatis mutandis for the `unless` expression. This is analogous to `()` in OCaml, Haskell, and Kapulet.
+If the test-expression evaluates to `#f`, then the `when` expression evaluates to a special "void" value; mutatis mutandis for the `unless` expression. This is analogous to `()` in OCaml, Haskell, and Kapulet. FIXME
 
 
-In the last three languages, the expressions in the then-branch and the else-branch of a conditional have to have the same type. You can't say `if test-expression then 0 else []`. Also, they expect the test-expression to evaluate specifically to a boolean value, not merely to `'false` or *anything else*. They are stricter about types here than Scheme is.
+In the last three languages, the expressions in the then-branch and the else-branch of a conditional have to have the same type. You can't say `if test-expression then 0 else []`. Also, they expect the test-expression to evaluate specifically to a boolean value, not merely to `'false` versus "anything else". They are stricter about types here than Scheme is.
 
 
-In the special case where both a then-branch and an else-branch evaluate to `()`, and the else-branch involves no complex expression but merely the literal `()`, then OCaml permits you to omit the else-branch. So in OCaml you can write this:
+In the special case where an else-branch evaluate to `()` (and thus so too must the then-branch), and the else-branch does so using no complex expression but merely the literal `()`, then OCaml permits you to omit that else-branch. So in OCaml you can write this:
 
 
-     if test-expression then then-result
+     if test_expression then then_result
 
 instead of
 
 
 instead of
 
-     if test-expression then then-result else ()
+     if test_expression then then_result else ()
+
+This is similar to Scheme's `when`-construction. Kapulet and Haskell have no analogue.
 
 
-This is similar to Scheme's `when`-expression. Kapulet and Haskell have no analogue.
 
 
 
 
 
 
@@ -515,7 +566,7 @@ and in OCaml you'd write:
     (* OCaml *)
     fun (x, y) z -> result
 
     (* OCaml *)
     fun (x, y) z -> result
 
-You may sometimes see &lambda;-expressions in OCaml written using `function` instead of `fun`. These overlap somewhat in their usage. The difference is that `function` only allocates a position for *one* argument pattern, so can't define curried functions. On the other hand, `function` can take multiple *variant* patterns for that single position. Thus with `function` you can say:
+You may sometimes see &lambda;-expressions in OCaml written using `function` instead of `fun`. These overlap somewhat in their usage. The difference is that `function` only allocates a position for *one* argument pattern, so can't straightforwardly define curried functions. (You can however embed `function` expressions inside other `function` expressions.) On the other hand, `function` can take multiple *variant* patterns for that single position. Thus with `function` you can say:
 
     (* OCaml *)
     function []    -> result1 |
 
     (* OCaml *)
     function []    -> result1 |
@@ -533,7 +584,7 @@ In Scheme, lambda expressions are written like this:
     ; Scheme
     (lambda (vars...) body-expressions...)
 
     ; Scheme
     (lambda (vars...) body-expressions...)
 
-Scheme only permits simple variables as its argument patterns here, and the lambda-expression can be defined with zero or more arguments:
+Scheme only permits simple variables as its argument patterns, and the lambda-expression can be defined to take zero or more arguments:
 
     ; Scheme
     (lambda () ...)
 
     ; Scheme
     (lambda () ...)
@@ -541,7 +592,10 @@ Scheme only permits simple variables as its argument patterns here, and the lamb
     (lambda (x y) ...)
     (lambda (x y z) ...)
 
     (lambda (x y) ...)
     (lambda (x y z) ...)
 
-There is special syntax for defining functions that may take varying numbers of arguments (recall `and` and `+`), to have them bind a single variable to a list containing all of their arguments (or all of the arguments after the third...). I won't explain that syntax here.
+We will discuss functions that "take zero arguments" a few weeks into the semester.
+
+There is special syntax for defining functions that may take *varying* numbers of arguments (recall `and` and `+`), where Scheme binds a single variable to a list containing all of the received arguments (or all of the arguments after the *n*th...). I won't explain that syntax here.
+
 
 
 
 
 
 
@@ -567,7 +621,7 @@ which is equivalent to:
       pat3  match expr3
     in result
 
       pat3  match expr3
     in result
 
-There is also a `letrec` form. In `let`, the bindings in `pat1` are in effect for the evaluation of all of `expr2`, `expr3`, and `result` (but not any further, if this is part of a more complex expression); similarly for the bindings in `pat2` and `pat3`. In `letrec`, all of the bindings on the left-hand side are in effect for all of the right-hand side expressions, as well as for the result.
+There is also a corresponding `letrec` form. In `let`, the bindings in `pat1` are in effect for the evaluation of all of `expr2`, `expr3`, and `result` (but not any further, if this is part of a more complex expression); similarly for the bindings in `pat2` and `pat3`. In `letrec`, all of the bindings on the left-hand side are in effect for all of the right-hand side expressions, as well as for the result.
 
 OCaml only has the second, more verbose form of this, and writes it a bit differently:
 
 
 OCaml only has the second, more verbose form of this, and writes it a bit differently:
 
@@ -580,7 +634,7 @@ OCaml only has the second, more verbose form of this, and writes it a bit differ
       pat3  = expr3
     in result
 
       pat3  = expr3
     in result
 
-If you want to define some mutually recursive functions with `letrec`, there's a special syntax for that, using `letrec ... and ... in ...`:
+If you want to define some mutually recursive functions with `letrec`, OCaml uses a special syntax for that, using `letrec ...` <code><em>and</em></code> `... in ...`:
 
     (* OCaml *)
     letrec
 
     (* OCaml *)
     letrec
@@ -589,7 +643,7 @@ If you want to define some mutually recursive functions with `letrec`, there's a
       odd   = fun x -> if x = 0 then false else even x
     in ...
 
       odd   = fun x -> if x = 0 then false else even x
     in ...
 
-Haskell has both of the syntactic forms that Kapulet does, though like OCaml, it uses `=` rather than `match`. And it wraps all multiple patterns with `{ ... }` (see earlier remarks about Haskell and whitespace/indentation FIXME):
+Haskell has both of the syntactic forms that Kapulet does, though like OCaml, it uses `=` rather than `match`. And it wraps all the binding clauses with `{ ... }` (see [[earlier remarks|#haskell-whitespace]] about Haskell and whitespace/indentation):
 
     -- Haskell
     let {
 
     -- Haskell
     let {
@@ -600,12 +654,13 @@ Haskell has both of the syntactic forms that Kapulet does, though like OCaml, it
 
 Also, in Haskell `let` always means `letrec`. There is no term in Haskell that means what simple `let` does in Kapulet and OCaml.
 
 
 Also, in Haskell `let` always means `letrec`. There is no term in Haskell that means what simple `let` does in Kapulet and OCaml.
 
-Scheme has *four or five* syntactic forms here, including `let`, `let*`, `letrec`, and `letrec*`. The difference between the last two [is subtle](http://stackoverflow.com/questions/13078165) and only arises in the presence of continuations; you can just use `letrec` for ordinary purposes. I won't try to explain the difference between `let` and `let*` here, except to say this:
+<a id=five-lets></a>
+Scheme has *four (or five)* syntactic forms here, including `let`, `let*`, `letrec`, and `letrec*`. The difference between the last two [is subtle](http://stackoverflow.com/questions/13078165) and only arises in the presence of continuations; you can just use `letrec` for ordinary purposes. I won't try to explain the difference between `let` and `let*` here, except to say this:
 
 1.  When there's only a single pattern-binding clause, as in `(let ((var expression)) result)`, `let` and `let*` work the same.
 2.  When there are multiple pattern-binding clauses, as in `(let ((var1 expression1) (var2 expression2)) result)`, then they work somewhat differently and `let*` is probably the one that works like you're expecting.
 
 
 1.  When there's only a single pattern-binding clause, as in `(let ((var expression)) result)`, `let` and `let*` work the same.
 2.  When there are multiple pattern-binding clauses, as in `(let ((var1 expression1) (var2 expression2)) result)`, then they work somewhat differently and `let*` is probably the one that works like you're expecting.
 
-The `let*` form is the one that corresponds to `let` in Kapulet. I recommend you get in the habit of just always using `let*` (or `letrec`) in Scheme.
+The `let*` form is the one that corresponds to `let` in Kapulet. I recommend you get in the habit of just always using `let*` (or `letrec`) in Scheme, instead of `let`.
 
 When you're at the "toplevel" of your program, or of a library/module/compilation-unit (the terminology differs), there is also another syntactic form possible. In Kapulet, you'd write:
 
 
 When you're at the "toplevel" of your program, or of a library/module/compilation-unit (the terminology differs), there is also another syntactic form possible. In Kapulet, you'd write:
 
@@ -624,7 +679,7 @@ Notice that this form ends with `end`, not with `in result`. The above is roughl
       ...
     in ... # rest of program or library
     
       ...
     in ... # rest of program or library
     
-That is, the bindings initiated by the clauses of the `let`-expression remain in effect until the end of the program or library. They can of course be "hidden" by subsequent bindings to new variables spelled the same way. The program:
+That is, the bindings initiated by the clauses of the `let`-construction remain in effect until the end of the program or library. They can of course be "hidden" by subsequent bindings to new variables spelled the same way. The program:
 
     # Kapulet
     let
 
     # Kapulet
     let
@@ -661,23 +716,23 @@ Haskell's "toplevel interpreter" (ghci) permits a syntactic form that looks supe
     let x = 2
     x
 
     let x = 2
     x
 
-but under the covers something quite different is happening (you're working "inside the IO Monad", except that simple expressions like `x` that don't evaluate to monadic values are also evaluated, as a special case). If you're writing in a *file* that you want Haskell to interpret or compile, on the other hand, you have to do something a bit different (which you can't easily also do inside ghci). [[Recall|topics/week1_advanced_notes#funct-declarations]] the shortcut by which we permitted:
+but under the covers something quite different is happening. (Specifically, you're working "inside the IO Monad", except that in this special context, expressions like `x` that don't evaluate to monadic values are permitted and evaluated. We don't expect that you will understand yet what any of this means.) If you're writing *in a file* that you want Haskell to interpret or compile, on the other hand, you have to do something a bit different (which you can't easily also do at the toplevel in ghci). [[Recall|topics/week1_advanced_notes#funct-declarations]] the shortcut by which we permitted:
 
     # Kapulet
     let
       f  match lambda pat1. body1;
 
     # Kapulet
     let
       f  match lambda pat1. body1;
-      g  match lambda pat2 pat3. body2;
-      ...
+      g  match lambda pat2 pat3. body2
+    in ...
 
 to be written more concisely as:
 
     # Kapulet
     let
       f pat1      = body1;
 
 to be written more concisely as:
 
     # Kapulet
     let
       f pat1      = body1;
-      g pat2 pat3 = body2;
-      ...
+      g pat2 pat3 = body2
+    in ...
 
 
-OCaml and Haskell permit that same shorthand. And what Haskell permits at the toplevel of *files* are just the bare binding clauses of such expressions, that is, without the surrounding `let` and `in ...`. That is, a Haskell file can look like this:
+OCaml and Haskell permit that same shorthand. And what Haskell permits at the toplevel of *files* are just the bare binding clauses of such expressions, that is, without the surrounding `let` and `in`. That is, a Haskell file can look like this:
 
     -- Haskell file.hs
     f pat1      = body1
 
     -- Haskell file.hs
     f pat1      = body1
@@ -685,14 +740,15 @@ OCaml and Haskell permit that same shorthand. And what Haskell permits at the to
     g pat2 pat3 = body2
     ...
 
     g pat2 pat3 = body2
     ...
 
-Note there are no semicolons here. These are called "declarations" of the functions `f` and `g`. Note that a single function can have multiple declarations (within a single scoping context), using different patterns:
+Note there are no semicolons here. These are called "toplevel declarations" of the functions `f` and `g`. A single function can have multiple declarations (within a single scoping context), using different patterns:
 
     -- Haskell file.hs
     f [] = 0
     f (x:xs) = 1 + f xs
 
 
     -- Haskell file.hs
     f [] = 0
     f (x:xs) = 1 + f xs
 
-defines `f` as a function that returns the length of a single List argument. (You can also do this *within* Haskell's `let`-constructions, too.) This is what corresponds *in Haskell files* to `let ... end` in Kapulet.
+defines `f` as a function that returns the length of a single List argument. (You can also do that *inside* Haskell's `let`-constructions, too.) This is what corresponds *in Haskell files* to `let ... end` in Kapulet.
 
 
+<a id=define></a>
 Scheme has a version of `letrec ... end`, which it writes as `define`. Thus in Scheme this:
 
     ; Scheme
 Scheme has a version of `letrec ... end`, which it writes as `define`. Thus in Scheme this:
 
     ; Scheme
@@ -706,6 +762,8 @@ evaluates the same as this:
             ... ; rest of program
                 )
 
             ... ; rest of program
                 )
 
+This is what we can call Scheme's [[fifth|#five-lets]] form of the `let` family.
+
 Some versions of Scheme permit you also to include `define` inside some (but not all) complex expressions. Thus you can write:
 
     (lambda (x)
 Some versions of Scheme permit you also to include `define` inside some (but not all) complex expressions. Thus you can write:
 
     (lambda (x)
@@ -724,36 +782,18 @@ There is no analogue to this in the other languages.
 
 
 
 
 
 
-FIXME
-
-symbol=?
-
-characters: #\c  #\xff  #\space  #\newline
-
-
-
-### Other functions
-
-Same in all: `succ`, `pred`, `fst`, `snd`.
-
-Same in Kapulet and Haskell (modulo the differences between multivalues and tuples), aren't predefined in OCaml: `id`, `const`, `flip`, `curry`, `uncurry`.
-
-Kapulet's `(comp)` is Haskell's `( . )`; isn't predefined in OCaml.
-
-Kapulet and Haskell both have `( $ )`; OCaml expresses as `( @@ )`. (OCaml also has `|>` to express the converse operation: `f x`, `f @@ x` and `x |> f` all mean the same.)
+### More to come ...
 
 
-Kapulet's `odd?` and `even?` are Haskell's `odd`, `even`; aren't predefined in OCaml.
+(This page is being worked on...)
 
 
-Kapulet's `swap` (defined in homework) is Haskell's `Data.Tuple.swap`.
-
-Kapulet's `dup` isn't predefined in Haskell but can be easily expressed as `\x -> (x, x)`.
 
 
+FIXME
 
 
+symbol=?
 
 
+characters: #\c  #\xff  #\space  #\newline
 
 
-### More to come ...
 
 
-(This page is being worked on...)