XGitUrl: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=rosetta1.mdwn;h=70866b1252e7b1e1865356f1c6d6025fcde7496f;hp=fa1895864d9e80aff7867338a246d0a401058e81;hb=6475bb8430df17a74277b7835ba9f2b334a4761f;hpb=b1b3498fa8a621ba0d9a6a00d6d83d8ef4998027
diff git a/rosetta1.mdwn b/rosetta1.mdwn
index fa189586..70866b12 100644
 a/rosetta1.mdwn
+++ b/rosetta1.mdwn
@@ 2,7 +2,7 @@
## Can you summarize the differences between your madeup language and Scheme, OCaml, and Haskell? ##
The madeup language we wet our toes in in week 1 is called Kapulet. (I'll tell you [the story behind its name](/randj.jpg) sometime.) The purpose of starting with this language is that it represents something of a center of gravity between Scheme, OCaml, and Haskell, and also lacks many of their idiosyncratic warts. One downside is that it's not yet implemented in a form that you can run on your computers. So for now, if you want to try out your code on a real mechanical evaluator, you'll need to use one of the other languages.
+The madeup language we wet our toes in in week 1 is called Kapulet. (I'll tell you [the story behind its name](/images/randj.jpg) sometime.) The purpose of starting with this language is that it represents something of a center of gravity between Scheme, OCaml, and Haskell, and also lacks many of their idiosyncratic warts. One downside is that it's not yet implemented in a form that you can run on your computers. So for now, if you want to try out your code on a real mechanical evaluator, you'll need to use one of the other languages.
Also, if you want to read code written outside this seminar, or have others read your code, for these reasons too you'll need to make the shift over to one of the established languages.
@@ 78,7 +78,7 @@ These relations are written in Haskell and OCaml as `&&`, ``, and `not`. (Hask
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 "falselike", like `0` and the empty list.
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`.
+Some Scheme implementations, such as Racket, permit `#true` and `#false` as synonyms for `#t` and `#f`. (These aliases are also mandated in "version 7", r7rs, of the Scheme standard.)
Scheme also recognizes the values `'true` and `'false`, but it treats `'false` as distinct from `#f`, and thus as a "truthlike" 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.
@@ 110,7 +110,13 @@ Scheme has no infix operators. It ruthlessly demands that all functions to be ap
(+ 3 2)
and the like. Moreover, in Scheme parentheses are never optional and never redundant. In contexts like this, the parentheses are necessary to express that the function is being applied; `+ 3 2` on its own is not a complete Scheme expression. And if the `+` were surrounded by its own parentheses, as in:
+and the like. Here is an example where the function to be applied is the result of evaluating a more complex expression:
+
+ ((if #t + *) 3 2)
+
+which will evaluate to `5`, not `6`.
+
+In Scheme the parentheses are never optional and never redundant. In expressions like `(+ 3 2)`, the parentheses are necessary to express that the function is being applied; `+ 3 2` on its own is not a complete Scheme expression. And if the `+` were surrounded by its own parentheses, as in:
((+) 3 2)
@@ 157,6 +163,25 @@ Here the last displayed line will fail, because `add` expects as its argument a
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.
+Here are some interesting functions we can define in Kapulet. See [[belowrosetta1#curriedpatterns]] for the pattern syntax used here.
+
+ # Kapulet
+ let
+ curry match lambda f. lambda x y. f (x, y);
+ uncurry match lambda g. lambda (x, y). g x y ;
+ uncurried_flip match lambda f. lambda (y, x). f (x, y)
+ curried_flip match lambda g. lambda y x. g x y;
+ in ...
+
+The function `curry` takes as an argument a function `f` that expects its arguments *uncurried*, and returns instead `lambda x y. f (x, y)`, a function that expects its arguments *curried*  but then does with them whatever `f` does. Going in the other direction, the function `uncurry` takes a function `g` that expects its arguments *curried*, and returns instead a function that expects its arguments *uncurried*  but then does with them whatever `g` does.
+
+The function `uncurried_flip` takes as an argument again an uncurried function `f`, and returns another function that also expects its arguments uncurried, but that expects them in the other order. `curried_flip` transforms a curried function `g` in the analogous way. These are both different from the function `swap` we defined in the [[course notestopics/week1_kapulet_advanced#functions]] as:
+
+ lambda (x, y) = (y, x)
+
+*That* function operates on a tuple and returns another tuple. The `..._flip` functions operate on functions, and transform them into other functions that expect their arguments in a different order.
+
+
[[As we mentioned in the course notestopics/week1_kapulet_advanced#sections]], in Kapulet, OCaml, and Haskell, there is a shorthand that enables you to write things like:
@@ 190,7 +215,7 @@ Fourth, in Kapulet, `(  10)` expresses λ `x. x  10` (consistently with
(  2) # (  2) 10 == 8
(0  )
(  ) (5, 3)

+
and here are their translations into natural Haskell:
@@ 444,7 +469,7 @@ Kapulet's `(comp)`, `odd?`, `even?`, and `swap` are Haskell's `( . )`, `odd`, `e
Kapulet's `dup` isn't predefined in Haskell but can be easily expressed as `\x > (x, x)`.
These are the same in Kapulet and Haskell (modulo the differences between [[Kapulet's multivaluestopics/week1_kapulet_intro#lightweight]] or "lightweight tuples" and Haskell's tuples): `id`, `const`, `flip`, `curry`, `uncurry`. None of these are predefined in OCaml.
+These are the same in Kapulet and Haskell (modulo the differences between [[Kapulet's multivaluestopics/week1_kapulet_intro#lightweight]] or "lightweight tuples" and Haskell's tuples): `id`, `const`, `curry`, `uncurry`. Kapulet's `curried_flip` is Haskell's `flip`. None of these are predefined in OCaml.
Kapulet and Haskell both have `( $ )`, which was explained [[in the course notestopics/week1_kapulet_advanced#dollar]]. OCaml expresses this as `( @@ )`. (OCaml also uses `>` to express the converse operation: `f x`, `f @@ x` and `x > f` all mean the same.)
@@ 605,6 +630,7 @@ This is similar to Scheme's `when` construction. Kapulet and Haskell have no ana
### Lambda expressions
+
In Kapulet you write λ expressions (sometimes called "anonymous functions") with a prefix of either λ or the spelledout `lambda`. That's followed by one or more patterns, separated by spaces, then a period, then a single expression which makes up the body of the function. When there are multiple patterns, the function expressed is *curried*, thus:
lambda (x, y) z. result
@@ 753,7 +779,7 @@ Notice that this form ends with `end`, not with `in result`. The above is roughl
pat1 match expr1;
...
in ... # rest of program or library

+
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