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