+### Pattern-matching
+
+The complex expression that's written like this in Kapulet:
+
+ # Kapulet
+ case some_expression of
+ 0 then result0;
+ 1 then result1;
+ x then resultx
+ end
+
+is written very similarly in Haskell:
+
+ -- Haskell
+ case some_expression {
+ 0 -> result0;
+ 1 -> result1;
+ x -> resultx
+ }
+
+Unlike the other languages we're discussing, Haskell pays special attention to the whitespace/indentation of what you write. This permits you to omit the `{`, `;`, and `}`s in the above, if you've got the indentation right. And that's how you will often see Haskell code displayed. On this website, though, I propose to always include the `{`s and so on when displaying Haskell code, because the indentation rules aren't 100% intuitive. It's easy to read properly-indented Haskell code, but until you've learned and practiced the specific rules, it's not always easy to write it.
+
+This is written only a little bit differently in OCaml:
+
+ (* OCaml *)
+ match some_expression with
+ 0 -> result0 |
+ 1 -> result1 |
+ x -> resultx
+
+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:
+
+ (* OCaml *)
+ match some_expression with
+ | 0 -> result0
+ | 1 -> result1
+ | x -> resultx
+
+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:
+
+ # Kapulet
+ case some_expression of
+ pat1 when guard then result1;
+ pat1 when different_guard then result2;
+ ((complex_pat) as var, pat4) then result3
+ end
+
+ -- Haskell
+ case some_expression {
+ pat1 | guard -> result1;
+ | different_guard -> result2;
+ (var@(complex_pat), pat4) -> result3
+ }
+
+ (* OCaml *)
+ match some_expression with
+ pat1 when guard -> result0 |
+ pat1 when different_guard -> result1 |
+ ((complex_pat) as var, pat4 -> result3
+
+
+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:
+
+ ; Scheme
+ (case some_expression
+ ((0) 'result0)
+ ((1) 'result1)
+ ((2 3 5) 'smallprime)
+ (else 'toobig))
+
+The results can be complex expressions; I just used bare symbols here for illustration. Note that the literal patterns in the first two clauses are surrounded by an extra pair of parentheses than you might expect. The reason is shown in the third clause, which begins `(2 3 5)`. This does not mean to match a list containing the values `2` `3` and `5`. Instead it means to match the simple value `2` *or* the simple value `3` *or* the simple value `5`. The final `else` clause is optional.
+
+The 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.
+
+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*.
+
+What programmers using standard Scheme tend to do instead is to use *predicates* that query the type and/or structure of an unknown value, and then take separate evaluation paths depending on the result. This can be done with an `if...then...else...` construction, or with Scheme's more general `cond` construction. In Scheme, these two are equivalent:
+
+ ; Scheme
+ (if test1 'result1
+ (if test2 'result2
+ (if test3 'result3 'somethingelse)))
+
+ (cond
+ (test1 'result1)
+ (test2 'result2)
+ (test3 'result3)
+ (else 'somethingelse))
+
+The tests tend to use predicates like `null?` (are you the empty list?), `pair?` (are you a non-empty list, whether proper or improper?), `list?` (are you a proper list, whether empty or not?), `symbol?`, `boolean?`, `number?`, `zero?` (you get the idea). But you can also use more complex tests you write on the spot, or use antecedently-defined functions:
+
+ ; Scheme...in case the parens left any doubt
+ (define smallprime? (lambda (x) (if (= x 2) #t (if (= x 3) #t (if (= x 5) #t #f)))))
+
+ (cond
+ ((= x 0) 'infant)
+ ((smallprime? x) 'myfavorite)
+ ((and (> x 10) (< x 20)) 'teenaged)
+ (else 'unknown))
+
+Remember that in Scheme, an expression doesn't have to evaluate to `#t` to be treated as "truth-like". *Every* value other than `#f` is treated as truth-like. So `(if 0 'zero 'nope)` evaluates to `'zero`.
+
+You may sometimes see Scheme `cond` constructions written with this kind of clause:
+
+ (cond
+ ...
+ (test-expression => function-value)
+ ...)
+
+That's the same as the following:
+
+ (cond
+ ...
+ (test-expression (function-value test-expression))
+ ...)
+
+Except that it only evaluates the test-expression once.
+
+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.
+
+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:
+
+ (when test-expression
+ result-expression1...)
+
+ (unless test-expression
+ result-expression2...)
+
+If the test-expression evaluates to `#f`, then the `when` expression evaluates to a special "void" value; mutatis mutandis for the `unless` expression. This is analogous to `()` in OCaml, Haskell, and Kapulet.
+
+In the last three languages, the expressions in the then-branch and the else-branch of a conditional have to have the same type. You can't say `if test-expression then 0 else []`. Also, they expect the test-expression to evaluate specifically to a boolean value, not merely to `'false` or *anything else*. They are stricter about types here than Scheme is.
+
+In the 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:
+
+ if test-expression then then-result
+
+instead of
+
+ if test-expression then then-result else ()
+
+This is similar to Scheme's `when`-expression. Kapulet and Haskell have no analogue.
+
+
+
+### Lambda expressions
+
+In Kapulet you write λ-expressions (sometimes called "anonymous functions") with a prefix of either λ 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:
+
+ lambda (x, y) z. result
+
+means the same as:
+
+ lambda (x, y). (lambda z. result)
+
+The parentheses could have been omitted around `lambda z. result`; they're just there to focus your attention.
+
+Haskell and OCaml are very similar to this, they just use some slightly different notation. In Haskell you'd write:
+
+ -- Haskell
+ \(x, y) z -> result
+
+and in OCaml you'd write:
+
+ (* OCaml *)
+ fun (x, y) z -> result
+
+You may sometimes see λ-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:
+
+ (* OCaml *)
+ function [] -> result1 |
+ x::xs -> result2
+
+whereas with `fun` you'd have to write:
+
+ (* OCaml *)
+ fun ys -> match ys with
+ [] -> result1 |
+ x::xs -> result2
+
+In Scheme, lambda expressions are written like this:
+
+ ; Scheme
+ (lambda (vars...) body-expressions...)
+
+Scheme only permits simple variables as its argument patterns here, and the lambda-expression can be defined with zero or more arguments:
+
+ ; Scheme
+ (lambda () ...)
+ (lambda (x) ...)
+ (lambda (x y) ...)
+ (lambda (x y z) ...)
+
+There is special syntax for defining functions that may take varying numbers of arguments (recall `and` and `+`), to have them bind a single variable to a list containing all of their arguments (or all of the arguments after the third...). I won't explain that syntax here.
+
+
+
+### Let, Letrec, and Define