A function value doesn't have any structure---at least none that's visible to the pattern-matching system. You can only match against simple patterns like `_` or the variable `f`.
-When matching a variable against a λ-generated function value in a `let`- or `letrec`-construction, there's an alternative syntax that you may find more convenient. This:
+When matching a λ-generated function value against a variable in a `let`- or `letrec`-construction, there's an alternative syntax that you may find more convenient. This:
`let`
`f match` λ`x.` φ`;`
### As-patterns ###
-Sometimes it's useful to bind variables against overlapping parts of a structure. For instance, suppose I'm writing a pattern that is to be matched against multivalues like `([10, 20], 'true)`. And suppose I want to end up with `ys` bound to `[10, 20]`, `x` bound to `10`, and `xs` bound to `[20]`. Using the techniques introduced so far, I have two options. First, I could bind `ys` against `[10, 20]`, and then initiate a second pattern-match to break that up into `10` and [20]`. Like this:
+Sometimes it's useful to bind variables against overlapping parts of a structure. For instance, suppose I'm writing a pattern that is to be matched against multivalues like `([10, 20], 'true)`. And suppose I want to end up with `ys` bound to `[10, 20]`, `x` bound to `10`, and `xs` bound to `[20]`. Using the techniques introduced so far, I have two options. First, I could bind `ys` against `[10, 20]`, and then initiate a second pattern-match to break that up into `10` and `[20]`. Like this:
- case [10, 20] of
+ case ([10, 20], 'true) of
[ys, _] then case ys of
x & xs then ...;
...
Alternatively, I could directly bind `x` against `10` and `xs` against `[20]`. But then I would have to re-cons them together again to get `ys`. Like this:
- case [10, 20] of
+ case ([10, 20], 'true) of
[x & xs, _] then let
ys match x & xs
in ...;
Both of these strategies work. But they are a bit inefficient. I said you didn't really need to worry about efficiency in this seminar. But these are also a bit cumbersome to write. There's a special syntax that enables us to bind all three of `ys`, `x`, and `xs` in the desired way, despite the fact that they will be matching against overlapping, rather than discrete, parts of the value `[10, 20]`. The special syntax looks like this:
- case [10, 20] of
+ case ([10, 20], 'true) of
[(x & xs) as ys, _] then ...
...
end
We've already come across the `id` function, namely λ `x. x`.
-Other common functions are `fst`, which takes two arguments and returns the first of them; `snd`, which takes two arguments and returns the second of them; and `swap`, which takes two arguments and returns them both but with their positions swapped. These functions can be defined like this:
+Other common functions are `fst`, which takes two arguments and returns the first of them; `snd`, which takes two arguments and returns the second of them; and `swap`, which takes two arguments and returns them both but with their positions swapped. A fourth function is `dup`, which takes one argument and returns it twice.
+These functions can be defined like this:
let
fst (x, y) = x;
snd (x, y) = y;
- swap (x, y) = (y, x)
- in (fst, snd, swap)
+ swap (x, y) = (y, x);
+ dup x = (x, x)
+ in (fst, snd, swap, dup)
+
+
+### Sections ###
+
+OCaml and Haskell have a convenient bit of syntax for the common case where you want a function like this:
+
+ lambda x. 10 - x
+
+or like this:
+
+ lambda x. x & ys
+
+or like this:
+
+ lambda (x, y). x + y
+
+They permit you to appreviate the first λ-expression as simply `(10 - )`. We know there's an argument missing, because the infix operator `-` demands two arguments, but we've only supplied one. So `(10 - )` expresses a function that takes an argument `x` and evaluates to `10 - x`. In other words, it expresses λ`x. 10 - x`. Similarly, `( & ys)` expresses a function that takes an argument `x` and evaluates to `x & ys`.
+
+All of this only works with infix operators like `-`, `&` and `+`. You can't write `(1 swap)` or `(swap 1)` to mean λ`x. swap (1, x)`.
+
+Can you guess what our shortcut for the last function will be? It's `( + )`. That
+expresses a function that takes two arguments `(x, y)` and evaluates to `x + y`.
+
+Wait a second, you say. Isn't that just what `+` does *already*? Why am I making a distinction between `+` and `( + )`? The difference is that bare `+` without any parentheses is an *infix* operator that comes between its arguments. Whereas when we wrap it with parentheses, it loses its special infix syntax and then just behaves like a plain variable denoting a function, like `swap`. Thus whereas we write:
+
+ x + y
+
+if we want to use `( + )`, we have to instead write:
+
+ ( + ) (x, y)
+
+It may not be obvious now why this would ever be useful, but sometimes it will be.
+
+All of these shorthands `(10 - )`, `( & ys)` and `( + )` are called "sections". I don't know exactly why.
+
+Confession: actually, what I described here diverges *a bit* from how OCaml and Haskell treat `( + )`. They wouldn't really write `( + ) (x, y)` like I did. Instead they'd write `( + ) x y`. We will look at the difference between these next week.