link to lambda_evaluator
[lambda.git] / rosetta1.mdwn
1 [[!toc levels=2]]
2
3 ** *This page is still being written!* **
4
5
6 ## Can you summarize the differences between your made-up language and Scheme, OCaml, and Haskell? ##
7
8 The made-up language we wet our toes in in week 1 is called Kapulet. (I'll tell you the story behind its name 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.
9
10 Also, if you want to read code written outside this class, or have others read your code, for these reasons too you'll need to make the shift over to one of the established languages.
11
12 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.)
13
14 ### Comments
15
16     ...  # this is a comment in Kapulet, that goes until the end of the line
17
18     ...  ; this is a comment in Scheme, that goes until the end of the line
19
20     ...  -- this is a comment in Haskell, that goes until the end of the line
21
22 Note that for Haskell's comments, the `--` must be immediately followed by something like a space or a letter. `-->` does not begin a comment; it's a legal operator symbol.
23
24 OCaml doesn't have comments of that sort. It only has "block" comments like this:
25
26     (* ... *)
27
28 which may last for several lines. These comments *nest*, so that:
29
30     (* ... (* inner *) ... *)
31
32 is a single comment.
33
34 Haskell also has block comments, though it `{- writes them differently -}`.
35 Haskell's block comments also nest.
36
37 Racket and Scheme also have block comments, though they `#| write them differently |#`.
38 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.)
39
40
41
42 ### Variables
43
44 Our [[syntax for variables|topics/week1#variables]] in Kapulet is close to that in the other languages. Haskell and OCaml differ only in that they do not permit trailing `?` or `!`; however, they do permit trailing `'`s (and even permit `'`s *in the middle* of a variable too, which Kapulet does not). Scheme permits all of these characters, plus many more punctuation symbols as well, to occur anywhere in a variable. Scheme also permits variables to begin with capital letters, or to consist solely of the single character `_`; but the other languages reserve these terms for special purposes.
45
46 In addition to the variables made of letters (more properly, of alphanumerics), Haskell and OCaml and Kapulet also permit some variables made exclusively of punctuation symbols, like `<` or Haskell's `>=>` and `<$>`. In Haskell, these always have infix syntax, and the variables made of letters never do. (But the former can have their infix syntax suppressed with parentheses, and the latter can be "flagged" to temporarily take on infix syntax, as we'll discuss below.)
47
48 In OCaml and Kapulet, some variables made of letters also have infix syntax, such as `comp` in Kapulet or `mod` in OCaml. I haven't presented to you the complex mechanisms needed to declare this.
49
50
51
52 ### Infix operators and parentheses
53
54
55 Kapulet, OCaml, and Haskell all understand some expressions like `+` to be infix operators. So you would write:
56
57     1 + 2
58
59 not:
60
61     + 1 2
62
63 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.
64
65 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:
66
67     3 `mod` 2
68
69 But without the `` ` ``, you'd have to write: `mod 3 2`.
70
71 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:
72
73     (+ 3 2)
74
75 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:
76
77     ((+) 3 2)
78
79 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.
80
81 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
82
83 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.
84
85 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.
86
87 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.
88
89
90 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:
91
92     (* OCaml *)
93     let add  = fun x y -> x + y in
94     let add2 = add 2 in
95         add2 3
96     ;;
97
98 will result in `5`.
99
100 In Scheme, the default would be to define `add` like this:
101
102     (define add (lambda (x y) (+ x y)))
103
104 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:
105
106     (define curried_add (lambda (x) (lambda (y) (+ x y))))
107     (define add2 (curried_add 2))
108     (add2 3)
109
110 will result in `5`. This is the best one can do in official Scheme, but there are various syntax extensions and macros out there to make it possible to write this sort of thing more succinctly.
111
112 OCaml and Haskell also permit defining functions in uncurried form:
113
114     (* OCaml *)
115     let add  = fun (x, y) -> x + y in
116     let add2 = fun add 2 in ...
117
118 Here the last displayed line will fail, because `add` expects as its argument a tuple of two numbers.
119
120 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.
121
122 [[As we mentioned|topics/week1_advanced_notes#sections]], in Kapulet, OCaml, and Haskell, there is a shorthand that enables you to write things like:
123
124     # Kapulet
125     let
126       ten_minus match lambda x. 10 - x;
127       and_ys    match lambda x. x & ys;
128       plus      match lambda (x, y). x + y
129     in (ten_minus, and_ys)
130
131 like this:
132
133     # Kapulet
134     let
135       ten_minus match (10 - );
136       and_ys    match ( & ys);
137       plus      match ( + )
138     in (ten_minus, and_ys)
139
140 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.
141
142 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:
143
144     # Kapulet
145     (0 - 2)
146     ( - 2)         # ( - 2) 10 == 8
147     (0 - )
148     ( - ) (5, 3)
149     
150
151 and here are their translations into Haskell:
152
153     -- Haskell
154     ( -2 )
155     (subtract 2)  -- subtract 2 10 == 8
156     negate        -- (0 - ) also works
157     ( - ) 5 3
158
159 OCaml expresses `(0 - )` or `negate` as `~-`. You can write `3 * (0 - 2)` in OCaml as either `3 * ( -2 )` or as `3 * ~-2`.
160
161 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."
162
163
164 ### Equality and Booleans
165
166 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.)
167
168 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:
169
170     ; Scheme
171     (and)
172     (and bool1)
173     (and bool1 bool2)
174     (and bool1 bool2 bool3)
175
176 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)`?
177
178 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 `&&`.)
179
180 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`.
181
182 Some Scheme implementations, such as Racket, permit `#true` and `#false` as synonyms for `#t` and `#f`.
183
184 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.
185
186
187
188 ### Sequences, Lists, and Tuples
189
190 In Kapulet, we have a notion I called a "sequence" which has an empty form `[]` and a cons-ing operator `&`, so that:
191
192     1 & 2 & 3 & []
193
194 can also be written:
195
196     [1, 2, 3]
197
198 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.)
199
200 Kapulet writes the operator that concatenates or appends sequences as `&&`. Thus:
201
202     # Kapulet
203     [1, 2] && [3, 4, 5]
204
205 evaluates to `[1, 2, 3, 4, 5]`. Haskell writes this operator as `++`. In Haskell, a `String` is just a List of `Char`, so `++` is also the operator we use to append strings:
206
207     -- Haskell
208     "over" ++ "due"
209
210 evaluates to `"overdue"`. In OCaml, `string`s aren't implemented as `list`s, so their append operators are different: `^` for `string`s and `@` for `list`s:
211
212     (* OCaml *)
213     [1; 2] @ [3; 4; 5] ;;
214     "over" ^ "due" ;;
215
216 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)]`.
217
218 Here are some list functions in Kapulet:
219
220     length
221     (&&)
222     # the following were defined in homework
223     empty?
224     tail
225     drop
226     take
227     split
228     filter
229     partition
230     map
231     map2
232     # the following were defined in extra credit
233     unmap2
234     takewhile
235     dropwhile
236     reverse
237     # new functions
238     join         # converts [[10, 20], [30], [], [40, 50]]
239                  # to [10, 20, 30, 40, 50] (but only "joining" a single layer of []s)
240     (mem)        # infix syntax, 2 mem [1, 2, 3] == 'true
241     nth          # nth [10, 20, 30] 1 == 20, because the first element
242                  # is at position 0; fails if index is out of bounds
243     all? p xs    # all? odd? [1, 3, 5] == 'true
244     any? p xs    # any? even? [1, 3, 5] == 'false
245
246
247
248 Here are the corresponding functions in Haskell:
249
250     length
251     (++)
252     null
253     tail     -- compare head, which fails on []
254     drop     {- but these are curried functions, so you write `drop n xs`
255                 not `drop (n, xs)` as in Kapulet -}
256     take
257     splitAt
258     filter
259     Data.List.partition
260     map
261     zipWith  {- zip handles the special case where f is the function that forms ordered pairs
262                 both zipWith and zip stop with the shortest list -}
263     unzip    {- unlike unmap2, doesn't take an explicit f argument
264                 just assumes it's (\(x, y) -> (x, y)) -}
265     takeWhile
266     dropWhile
267     reverse
268     concat   -- corresponding to join
269     elem     -- not infix syntax, but often written as: 2 `elem` [1, 2, 3]
270     (!!)     -- infix syntax: [10, 20, 30] !! 1 == 20; fails if index is out of bounds
271     all p xs
272     any p xs
273
274
275
276 Here they are in OCaml:
277
278     length
279     (@)          (* or List.append *)
280     (* no function corresponding to empty? *)
281     List.tl      (* compare List.hd, which fails on [] *)
282     (* no function corresponding to drop or take *)
283     (* no function corresponding to split; OCaml uses List.split to mean something else *)
284     List.filter  (* also List.find_all *)
285     List.partition
286     List.map
287     List.map2    (* compare List.combine, like Haskell's zip
288                     both map2 and combine fail if the lists are different lengths *)
289     List.split   (* like Haskell's unzip, doesn't take an f argument *)
290     (* no function corresponding to takewhile or dropwhile *)
291     List.rev
292     List.concat  (* also List.flatten, which still only "joins" a single layer of []s *)
293     List.mem     (* not infix syntax *)
294     List.nth     (* List.nth [10; 20; 30] 1 = 20; fails if index is out of bounds *)
295     List.for_all p xs
296     List.exists p xs
297
298
299 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:
300
301 1.  these structures in Scheme can contain heterogenously-typed elements, including further `list`s and `vector`s in some positions but not in others
302 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
303 elements at different stages in a program's evaluation
304
305 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).
306
307 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:
308
309     (list)
310
311 and lists with more elements like this:
312
313     (list 10)
314     (list 10 x)
315     (list 10 x 'alpha)
316     (list 10 x 'alpha (list 'beta 'gamma) 'delta 20)
317
318 In the preceding, the `x` is a variable and is evaluated to be whatever value it's bound to in the context where the displayed expressions are being evaluated. If one has a list specification that contains no variables, no matter how deeply embedded, then a certain shorthand becomes available, using a `'` prefix, like this:
319
320     '()                          ; same as (list)
321     '(10)                        ; same as (list 10)
322     '(10 alpha)                  ; same as (list 10 'alpha)
323     '(10 alpha (beta gamma) 20)  ; same as (list 10 'alpha (list 'beta 'gamma) 20)
324
325 Scheme can also write <code>'<em>something</em></code> as <code>(quote <em>something</em>)</code>. (The `quote` is not a function being applied to some argument; this is a special syntax that only superficially *looks* like a function application.)
326
327
328 Here are the `list` functions in Scheme corresponding to the functions listed in the other languages:
329
330     cons              ; corresponds to Kapulet's ( & ), Haskell's ( : ), OCaml's `::`
331     length
332     append            ; corresponds to Kapulet's ( && ), Haskell's ( ++ ), OCaml's ( @ )
333                       ; can be applied to one or more arguments
334     null?             ; corresponds to Kapulet's empty?, Haskell's null
335     car               ; corresponds to Haskell's head
336     cdr               ; corresponds to Kapulet's and Haskell's tail
337     (list-tail xs k)  ; corresponds to Kapulet's drop (k, xs); fails if out-of-bounds
338     ; no official function corresponding to take or split or filter or partition
339     map               ; corresponds to Kapulet's map and map2
340                       ; can take one or more list arguments
341     ; no official function corresponding to unmap2 or takewhile or dropwhile
342     reverse
343     ; no official function corresponding to join/concat
344     member            ; corresponds to Kapulet's (mem) and Haskell's elem
345     (list-ref xs k)   ; corresponds to Kapulet's `nth xs k`
346     ; no official function corresponding to all or any
347
348 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.
349
350
351
352 ### Pattern-matching
353
354 The complex expression that's written like this in Kapulet:
355
356     # Kapulet
357     case some_expression of
358       0 then result0;
359       1 then result1;
360       x then resultx
361     end
362
363 is written very similarly in Haskell:
364
365     -- Haskell
366     case some_expression {
367       0 -> result0;
368       1 -> result1;
369       x -> resultx
370     }
371
372 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.
373
374 This is written only a little bit differently in OCaml:
375
376     (* OCaml *)
377     match some_expression with
378       0 -> result0 |
379       1 -> result1 |
380       x -> resultx
381
382 Note there is no closing `end` or `}`. You can enclose the whole expression in parentheses if you want to, and when embedding it in some larger expressions (like another `match` expression), you may need to. Sometimes the `|` dividers are written at the start of a line, and you are allowed to include an extra one before the first line, so you could also see this written as:
383
384     (* OCaml *)
385     match some_expression with
386       | 0 -> result0
387       | 1 -> result1
388       | x -> resultx
389
390 The syntax for [[guards|topics/week1_advanced_notes#guards]] and [[as-patterns|topics/week1_advanced_notes#as-patterns]] also only varies slightly between these languages:
391
392     # Kapulet
393     case some_expression of
394       pat1   when guard             then result1;
395       pat1   when different_guard   then result2;
396       ((complex_pat) as var, pat4)  then result3
397     end
398
399     -- Haskell
400     case some_expression {
401       pat1 | guard              -> result1;
402            | different_guard    -> result2;
403       (var@(complex_pat), pat4) -> result3
404     }
405
406     (* OCaml *)
407     match some_expression with
408       pat1   when guard             -> result0 |
409       pat1   when different_guard   -> result1 |
410       ((complex_pat) as var, pat4   -> result3
411
412
413 The official Scheme standard only provides for a limited version of this. There is a `case` construction, available since at least "version 5" of the Scheme standard (r5rs), but it only accepts literal values as patterns, not any complex patterns containing them or any patterns containing variables. Here is how it looks:
414
415     ; Scheme
416     (case some_expression
417       ((0) 'result0)
418       ((1) 'result1)
419       ((2 3 5) 'smallprime)
420       (else 'toobig))
421
422 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.
423
424 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.
425
426 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*.
427
428 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:
429
430     ; Scheme
431     (if test1 'result1
432               (if test2 'result2
433                         (if test3 'result3 'somethingelse)))
434
435     (cond
436       (test1 'result1)
437       (test2 'result2)
438       (test3 'result3)
439       (else  'somethingelse))
440
441 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:
442
443     ; Scheme...in case the parens left any doubt
444     (define smallprime? (lambda (x) (if (= x 2) #t (if (= x 3) #t (if (= x 5) #t #f)))))
445
446     (cond
447       ((= x 0) 'infant)
448       ((smallprime? x) 'myfavorite)
449       ((and (> x 10) (< x 20)) 'teenaged)
450       (else 'unknown))
451
452 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`.
453
454 You may sometimes see Scheme `cond` constructions written with this kind of clause:
455
456     (cond
457       ...
458       (test-expression => function-value)
459       ...)
460
461 That's the same as the following:
462
463     (cond
464       ...
465       (test-expression (function-value test-expression))
466       ...)
467
468 Except that it only evaluates the test-expression once.
469
470 The clauses in Scheme's `cond` expressions can contain *multiple* expressions after the test. This only becomes useful when you're working with mutable values and side-effects, which we've not gotten to yet. The `if` expressions only take a single expression for the "then" branch and a single expression for the "else" branch. You can turn a complex series of expressions, which may involve side-effects, into a single expression by wrapping it in a `(begin ...)` construction. The `(begin ...)` construction as a whole evaluates to whatever the last expression it contains does.
471
472 Scheme standards after r5rs also provide two further conditional constructions, which are for the situations where you want to perform a meaningful action only on the "then" branch, or only on the "else" branch:
473
474     (when test-expression
475        result-expression1...)
476
477     (unless test-expression
478        result-expression2...)
479
480 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.
481
482 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.
483
484 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:
485
486      if test-expression then then-result
487
488 instead of
489
490      if test-expression then then-result else ()
491
492 This is similar to Scheme's `when`-expression. Kapulet and Haskell have no analogue.
493
494
495
496 ### Lambda expressions
497
498 In Kapulet you write &lambda;-expressions (sometimes called "anonymous functions") with a prefix of either &lambda; or the spelled-out `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:
499
500     lambda (x, y) z. result
501
502 means the same as:
503
504     lambda (x, y). (lambda z. result)
505
506 The parentheses could have been omitted around `lambda z. result`; they're just there to focus your attention.
507
508 Haskell and OCaml are very similar to this, they just use some slightly different notation. In Haskell you'd write:
509
510     -- Haskell
511     \(x, y) z -> result
512
513 and in OCaml you'd write:
514
515     (* OCaml *)
516     fun (x, y) z -> result
517
518 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:
519
520     (* OCaml *)
521     function []    -> result1 |
522              x::xs -> result2
523
524 whereas with `fun` you'd have to write:
525
526     (* OCaml *)
527     fun ys -> match ys with
528                 []    -> result1 |
529                 x::xs -> result2
530
531 In Scheme, lambda expressions are written like this:
532
533     ; Scheme
534     (lambda (vars...) body-expressions...)
535
536 Scheme only permits simple variables as its argument patterns here, and the lambda-expression can be defined with zero or more arguments:
537
538     ; Scheme
539     (lambda () ...)
540     (lambda (x) ...)
541     (lambda (x y) ...)
542     (lambda (x y z) ...)
543
544 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.
545
546
547
548 ### Let, Letrec, and Define
549
550 Kapulet has the syntax:
551
552     # Kapulet
553     let
554       pat1  match expr1;
555       pat2  match expr2;
556       pat3  match expr3
557     in result
558
559 which is equivalent to:
560
561     # Kapulet
562     let
563       pat1  match expr1
564     in let
565       pat2  match expr2
566     in let
567       pat3  match expr3
568     in result
569
570 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.
571
572 OCaml only has the second, more verbose form of this, and writes it a bit differently:
573
574     (* OCaml *)
575     let
576       pat1  = expr1
577     in let
578       pat2  = expr2
579     in let
580       pat3  = expr3
581     in result
582
583 If you want to define some mutually recursive functions with `letrec`, there's a special syntax for that, using `letrec ... and ... in ...`:
584
585     (* OCaml *)
586     letrec
587       even  = fun x -> if x = 0 then true else odd x
588     and
589       odd   = fun x -> if x = 0 then false else even x
590     in ...
591
592 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):
593
594     -- Haskell
595     let {
596       pat1  = expr1;
597       pat2  = expr2;
598       pat3  = expr3
599     } in result
600
601 Also, in Haskell `let` always means `letrec`. There is no term in Haskell that means what simple `let` does in Kapulet and OCaml.
602
603 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:
604
605 1.  When there's only a single pattern-binding clause, as in `(let ((var expression)) result)`, `let` and `let*` work the same.
606 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.
607
608 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.
609
610 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:
611
612     # Kapulet
613     let
614       pat1  match expr1;
615       ...
616     end
617     ... # rest of program or library
618
619 Notice that this form ends with `end`, not with `in result`. The above is roughly equivalent to:
620
621     # Kapulet
622     let
623       pat1  match expr1;
624       ...
625     in ... # rest of program or library
626     
627 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:
628
629     # Kapulet
630     let
631       x  match 0
632     end
633     let
634       x  match 1
635     end
636     x
637
638 evaluates to `1`, just like:
639
640     # Kapulet
641     let
642       x  match 0
643     in let
644       x  match 1
645     in x
646
647 does. There's a similar form for `letrec`.
648
649 OCaml can do the same:
650
651     let
652       x = 0;;
653     let
654       x = 1;;
655     x
656
657 The double-semicolons are hints to OCaml's "toplevel interpreter" that a syntactic unit has finished. In some contexts they're not needed, but it does no harm to include them if you're not sure.
658
659 Haskell's "toplevel interpreter" (ghci) permits a syntactic form that looks superficially quite like these:
660
661     let x = 2
662     x
663
664 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:
665
666     # Kapulet
667     let
668       f  match lambda pat1. body1;
669       g  match lambda pat2 pat3. body2;
670       ...
671
672 to be written more concisely as:
673
674     # Kapulet
675     let
676       f pat1      = body1;
677       g pat2 pat3 = body2;
678       ...
679
680 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:
681
682     -- Haskell file.hs
683     f pat1      = body1
684
685     g pat2 pat3 = body2
686     ...
687
688 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:
689
690     -- Haskell file.hs
691     f [] = 0
692     f (x:xs) = 1 + f xs
693
694 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.
695
696 Scheme has a version of `letrec ... end`, which it writes as `define`. Thus in Scheme this:
697
698     ; Scheme
699     (define var1 expr1)
700     ... ; rest of program
701
702 evaluates the same as this:
703
704     ; Scheme
705     (letrec ((var1 expr1))
706             ... ; rest of program
707                 )
708
709 Some versions of Scheme permit you also to include `define` inside some (but not all) complex expressions. Thus you can write:
710
711     (lambda (x)
712       (define var1 expr1)
713       ...)
714
715 instead of:
716
717     (lambda (x)
718       (letrec ((var1 expr1))
719       ...))
720
721 There is no analogue to this in the other languages.
722
723
724
725
726
727 FIXME
728
729 symbol=?
730
731 characters: #\c  #\xff  #\space  #\newline
732
733
734
735 ### Other functions
736
737 Same in all: `succ`, `pred`, `fst`, `snd`.
738
739 Same in Kapulet and Haskell (modulo the differences between multivalues and tuples), aren't predefined in OCaml: `id`, `const`, `flip`, `curry`, `uncurry`.
740
741 Kapulet's `(comp)` is Haskell's `( . )`; isn't predefined in OCaml.
742
743 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.)
744
745 Kapulet's `odd?` and `even?` are Haskell's `odd`, `even`; aren't predefined in OCaml.
746
747 Kapulet's `swap` (defined in homework) is Haskell's `Data.Tuple.swap`.
748
749 Kapulet's `dup` isn't predefined in Haskell but can be easily expressed as `\x -> (x, x)`.
750
751
752
753
754 ### More to come ...
755
756 (This page is being worked on...)
757
758
759
760 ### Further Installments ...
761
762 We will expand these comparisons (on separate web pages) as we introduce additional ideas in the course, such as types and monads and continuations.
763
764
765
766
767
768
769 FIXME
770
771
772 ## Offsite Readings comparing Scheme, OCaml, and Haskell ##
773
774
775 *   [Haskell for OCaml Programmers](http://science.raphael.poss.name/haskell-for-ocaml-programmers.pdf)
776 *   [Introduction to OCaml for Haskellers](http://foswiki.cs.uu.nl/foswiki/pub/Stc/BeyondFunctionalProgrammingInHaskell:AnIntroductionToOCaml/ocaml.pdf), [another](http://blog.ezyang.com/2010/10/ocaml-for-haskellers/)
777 *   Haskell Wiki on [OCaml](https://wiki.haskell.org/OCaml)
778 *   [ML Dialects and Haskell](http://hyperpolyglot.org/ml)
779 *   [Differences between Haskell and SML?](http://www.quora.com/What-are-the-key-differences-between-Haskell-and-Standard-ML?browse)
780 *   [Comparing SML to OCaml](http://www.mpi-sws.org/~rossberg/sml-vs-ocaml.html)
781
782
783
784
785 ## Why did you name these pages "Rosetta"? ##
786
787 The [Rosetta Stone](https://en.wikipedia.org/wiki/Rosetta_Stone) is a famous slab discovered during Napoleon's invasion of Egypt, that had the same decree written in ancient Greek (which modern scholars understood) and two ancient Egyptian scripts (which they didn't). The slab enabled us to recover understanding of those Egyptian scripts; and has since come to be a symbol for the simultaneous expression of a single idea in multiple languages. A number of websites do this for various programming languages:
788
789 <table><th>
790 <td>Scheme
791 <td>OCaml
792 <td>Haskell
793 <tr>
794 <td rowspan=10>&nbsp;
795 <td><a href="http://rosettacode.org/wiki/Category:Scheme">Rosetta Code</a>
796 <td><a href="http://rosettacode.org/wiki/Category:OCaml">Rosetta Code</a>
797 <td><a href="http://rosettacode.org/wiki/Category:Haskell">Rosetta Code</a>
798 <tr>
799 <td><a href="http://pleac.sourceforge.net/pleac_guile/index.html">PLEAC</a>
800 <td><a href="http://pleac.sourceforge.net/pleac_ocaml/index.html">PLEAC</a>
801 <td><a href="http://pleac.sourceforge.net/pleac_haskell/index.html">PLEAC</a>
802 <tr>
803 <td>n/a
804 <td colspan=2 align=center><hr><a href="http://langref.org/ocaml+haskell/solved">langref.org</a>
805 <tr>
806 <td><a href="http://www.codecodex.com/wiki/Category:Scheme">code codex</a>
807 <td><a href="http://www.codecodex.com/wiki/Category:Objective_Caml">code codex</a>
808 <td><a href="http://www.codecodex.com/wiki/Category:Haskell">code codex</a>
809 <tr>
810 <td><a href="http://community.schemewiki.org/?ninety-nine-scheme-problems">99 problems</a>
811 <td><a href="http://ocaml.org/learn/tutorials/99problems.html">99 problems</a>
812 <td><a href="https://wiki.haskell.org/H-99:_Ninety-Nine_Haskell_Problems">99 problems</a>
813 </table>
814
815 See also the [Project Euler](https://projecteuler.net/) programming challenges.