1 ----- Forwarded message from Jim Pryor <jim@jimpryor.net> -----
5 Probably we won't want to explicitly give this to them until week 2 (or
6 later), but I jotted it down now so that we might agree about it and
10 These languages have VALUES of various TYPES. For instance, the number 2
11 is a value of the type integer. The string "horse" is a value of the
12 type string. Functions are also values. Their type depends on the values
13 of their domain and range. For instance, the successor function is a
14 value of the type integer -> integer. The plus function is a value of
15 the type <two integers> -> integer. I'm fudging a bit here with the <two
16 integers>; we'll come back to this and talk about the fudge soon.
18 We can talk equally of expressions having types: they have the types of the values they express.
20 (Sometimes the "untyped" lambda calculus is said to be "singly-typed". It may nor may not be helpful to think of it that way. If its expressions do have a type, though, it's a type T such that functions from T -> T are also of type T. Myself I find it easier to think "untyped.")
23 In some of the languages, one refers to (and sometimes quantifies over) the types in the object language itself; so the object language itself has syntax for talking about types. We'll be discussing this later in the course. For now I'm just saying what notation will eventually be so used.
25 You need to keep straight about the difference between Constants of a
26 given sort, Object-language Variables of the same sort, and Metalinguistic Schemas of that sort. I say "sort" here because you have this same three-way divide with BOTH expressions that express values and expressions that express types.
28 Sticking just to values, here are some examples of constants: 2, 3, +,
29 *, "horse", and so on.
31 Here are some examples of object-language
32 variables: x, y10, first, second_place, and so on (you needn't stick to a
33 single letter). x', x'', and so on are also typically used as variables.
34 All the languages we'll be looking at will permit this syntax.
36 Conventions for metalinguistic schemas vary. In logic textbooks, one
37 often sees lower-case Greek letters used in this way. But in the fields
38 we'll be looking at, those are often used specifically as schematic
39 letters for TYPES. For schematic letters for VALUES, we'll go with the
40 convention that uses Capital Letters. For example:
41 E is some expression of the lambda calculus. E may be "x" or "lambda
42 x: x" or "(lambda x: x y) (lambda z: w)" or whatever.
43 (M N) is another expression of the lambda calculus, where some
44 possibly complex expression M is applied to another possibly complex
51 value variables in OCaml: start with lower case letter, can be
52 followed by any letter or number or _ or '
53 value variables in lambda calculus: no fixed rules, but we'll
54 use the OCaml conventions, which is what you commonly see in practice.
55 value variables in Scheme: all the OCaml variables are permitted.
56 Some Schemes are case-sensitive, others aren't, others let you flip a
57 switch to decide. To avoid worrying about it, never use "firstPlace" as a
58 variable if you also use "firstplace" as a variable. Scheme also permits
59 very funky variable names, like "*add*" and "are-there-three-yet?" and
62 Remember, value variables can be bound to values of various types,
65 value constants in lambda calculus: some lambda calculi have
66 primitive values in them, such as the number 0. But the mainstream ones
67 don't have any primitive values of any sort. All you've got are
68 variables, lambda abstractions of other stuff you've got, and
69 applications of other stuff you've got. If you want numbers or boolean
70 constants, you've got to "encode" them or build them yourself out of the
71 materials just described. We'll be looking at how that's done.
74 simple values: 2, 3; #t, #f; #\h is a character (the eighth
75 letter in the Latin alphabet)
77 in Scheme, like in the lambda calculus, functions always go
78 to the left: so you write (+ 2 3) not 2 + 3.
79 compound non-function values: "h" "horse" and "" are three
80 strings of different length (the string "h" is built from the character
81 #\h but isn't identical to it; these values have different types)
82 '(2 . 3) or (cons 2 3) is an ordered pair
83 '(2 3) or (list 2 3) is a list. Other lists (with different
84 lengths) are (list), (list 2), (list 2 3 4).
87 pretty much like Scheme, except that:
88 the ordered pair is written (2, 3)
89 the list is written [2; 3]
90 the eighth character in the Latin alphabet is written 'h'
91 the string consisting just of that character is written "h", as
93 true and false are written like that
94 most functions are written leftmost, as in Scheme and the lambda
95 calculus. But a few familiar binary operators can be written infix: so
96 you can write 2 + 3. You can also write it function-leftmost, like so:
98 Here the parentheses are needed so that the OCaml parser can
99 figure out what you're doing.
101 Aside on parentheses:
103 Parentheses are often optional in lambda caluli and also in OCaml.
104 If M, N, and P are syntactically simple expressions, you can write ((M N) P), but you don't have to: you can also just write M N P. These mean exactly the same thing. To write M (N P) you do need the parentheses.
106 In Scheme, EVERY parenthesis is meaningful and they are never
107 optional. Typically parentheses mean to "apply this function to these
108 arguments". So to add 2 and 3, you write (+ 2 3). In Scheme, this is different from
109 ((+ 2) 3) --- we'll talk about this later. For the purposes of our
110 course, it would be more convenient if Scheme behaved more like lambda
111 calculi and OCaml here.
112 However, parentheses sometimes also do other duty in Scheme: if you
113 print out the list (list 2 3) (also writable '(2 3)), the interpreter
114 will display: (2 3). And the pair (cons 2 3) will display: (2 . 3). The
115 parentheses here don't mean that 2 is being used as an argument.
116 However, if you asked Scheme to "evaluate" one of these, it would think
117 you were using 2 as a function.
118 There are good reasons why parentheses are used in "both" of these
119 ways in Scheme. We'll leave them for you to discover and read about.
120 Another example of parentheses in Scheme: most of the parentheses in
121 (let ((x 2)) (+ x 1)) don't play the role of applying functions to arguments.
126 We've described value variables and value constants in all of these
127 languages. As we said, we'll follow the convention of using capital
128 Latin letters as metalinguistic schemas for value expressions in each of
129 the languages. Typically these schemas can stand for expressions of any
130 syntactic complexity. When we want them to stand for syntactically
131 simple expressions, we'll say so.
134 When we get to types, we'll use small Greek letters as metalinguistic
135 schemas for type expressions (of any syntactic complexity, unless we say
138 There are no type expressions or variables in standard Scheme.
140 Type expressions in OCaml---whether type variables or constants
141 representing predefined types---are usually written with lower-case
142 expressions (following the same rules as object-language variables). So
143 "stack" in OCaml could designate a type or a value; it depends on the
146 OCaml (and all languages of its ML family) does have a special rule for
147 type variables bound by quantifiers. Here you use 'x, 'stack, and so
148 on. It looks like the prefix ' used in Scheme, but it's used very
149 differently. Also, don't confuse the type variable 'x with the value
153 What's the difference between the type variable stack and the type
154 variable 'stack? You use stack when you're binding it to a specific type
155 value. So you might say:
156 type stack = HERE SOME COMPLEX EXPRESSION THAT EXPRESSES A TYPE
157 On the other hand, you use 'stack when you're only binding the variable
158 with a quantifier: when you're saying such-and-such holds for EVERY type
162 It would be good for us to fix on conventions for object-language type
163 constants and variables in the lambda calculi (and to use something
164 other than small Greek letters, because they are metalanguage schemas).
165 I don't know whether there are uniform conventions about this.
169 ----- End forwarded message -----
170 ----- Forwarded message from Jim Pryor <jim@jimpryor.net> -----
172 1. Introducing and pounding on difference between declarative and
173 imperatival computation.
178 Scheme (functional parts) OCaml (functional parts)
182 Untyped lambda calculus |
184 Combinatorial logic |
187 ============ Turing complete (briefly explain)=======================
189 more advanced type systems |
190 e.g. polymorphic types (System F)
193 simply typed lambda calculus
194 what linguists standardly use
197 Imagine in third column to the right of the others:
199 Typical languages like C, Python
200 Imperatival parts of Scheme, OCaml
203 3. How the same thing looks in each of these:
205 in untyped lambda: add three two
206 (if those are predefined, e.g. three defined as \sz.s(s(sz))
207 in combinatorial logic: too long, pieces look like: S(BKI)K
209 in Scheme: (let* [(three 3)
213 in OCaml: let three = 3 in
222 Mutation in C: int x = 0;
225 in OCaml: let x = ref 0 in
228 in Scheme: (let* [(x (box 0))]
232 Pound more on how this is different, and we won't be looking at until a
233 lot of groundwork has been laid.
236 4. Question: how can mutation be something fundamentally new if some of
237 these other languages without it are Turing complete? How are they able
238 to encode/represent the same computations, without using mutation? (And
239 in fact, Turing completeness is more than is needed for this.)
241 Say a few words to sketch / reserve a place for an answer that they
242 should be able to appreciate at the end of the course.
245 5. Commonly people think of programming/computation as a sequence of
246 changes. But in the languages we'll first be looking at, there are no
247 changes. And moreover, there isn't at the beginning a very useful notion
248 of sequencing, either.
250 You can write sequences: in Scheme: (begin M N P Q R)
251 in OCaml: begin M; N; P; Q; R end
254 however, these just have the value of R. So if none of the earlier
255 expressions have any side-effects / make any changes, a sequence ending
256 in R means just the same as R.
259 I'm fudging a bit here: there may also be a difference if some of the
260 earlier expressions in the sequence are incomputable, and so have what we'll
261 later be calling the "bottom" value. More on this when we talk about
262 evaluation order in a few classes.
264 Another difference is that sequencing is explicit about what order the
265 expressions get evaluated in, and this can affect computational
266 efficiency. But that's not about their semantics.)
268 There's a bit of syntactic shorthand, which I'll introduce in a bit,
269 that LOOKS LIKE a kind of sequencing. However, once you understand what
270 it's shorthand for, you'll see that fundamentally, there's no sequencing
273 6. Instead of sequencing, we just have the
274 evaluation/simplification/"reducing" of single, often syntactically
275 complex, expressions.
276 Later, when we introduce changes and sequencing, we'll do so in a
277 way that makes that a new piece of syntactic structure.
282 More "how to say the same thing in different languages"
285 1. Anonymous functions
288 for example, \x. times x five
289 here times and five are free variables, we suppose they're bound
290 to appropriate values by the surrounding linguistic context
292 Scheme: (lambda (x) B)
293 for example, (lambda (x) (* x 5))
294 -- perhaps aside about role of parens in Scheme should go here
297 OCaml: fun x -> x * 5
298 or: fun x -> ( * ) x 5
301 2. Binding variables to values with "let"
304 (let* [(x A) (y A')] B)
306 explain that Scheme also has a simple "let", which sometimes
307 has a different meaning from let*, and that they usually will
308 want let*, so we'll stick to using that in our pedagogy
310 explain that there's also a letrec, which does automatically
311 something that we want them to learn how to do by hand
312 so for the time being we'll avoid it
319 for example: let x = 3 + 1 in
323 explain OCaml also has "let rec", which we'll also avoid for now
326 3. binding with "let" same as supplying as an argument to a function
328 Scheme's (let* [(x A)] B) and OCaml's let x = A in B are the same
333 in Scheme: ((lambda (x) B) A)
335 in OCaml: (fun x -> B) A
338 4. Functions can also be bound to variables
340 in Scheme: (let* [(f (lambda (x) B))] ...)
342 in OCaml: let f = fun x -> B in ...
343 OCaml shorthand: let f x = B in ...
346 (let* [(f (lambda (x) B))] (f A))
347 as we've said, means the same as:
349 and also means the same as:
352 Similarly, this in OCaml:
353 let f = fun x -> B in
358 as we've said, means the same as:
360 and also means the same as:
364 6. What if you want to do something like this:
366 (let* [(x A)] ...rest of the file or interactive session...)
368 let x = A in ...rest of the file or interactive session...
370 You can override these bindings:
371 (let* [(x A)] (let* [(x A')] B))
375 The closest/innermost binding of x "shadows" or overrides more outer
378 Scheme and OCaml have shorthands for wrapping a binding around the rest
379 of the file or interactive session.
381 In Scheme it's written like this:
383 ...rest of file or session...
385 In OCaml it's written like this:
387 ...rest of file or session...
389 This is the construction that I said misleadingly looked like
390 sequencing. Fundamentally, though, it's just a syntactic shorthand for
391 complex let-expressions that don't involve any sequencing.
394 7. One more bit of shorthand, which is very often used.
397 (define f (lambda (x) B))
398 can be written like this:
401 Similarly, this in OCaml:
403 can be written like this:
406 (Compare how "let f = fun x -> B in ..." can be written "let f x = B in
412 Subject: Concatanation (!= sequencing)
414 When we concatenate expressions in these languages, we'll usually be
415 treating the leftmost expression as a function, and the rest of the
416 expressions as arguments to it.
420 in lambda and OCaml treat M as as the function, and N as its first
421 argument. M N should evaluate to another function, which takes P as its
422 first argument. So this is equivalent to:
426 If you want M (N P) instead, you need to explicitly use parentheses.
429 add three two = (add three) two
431 In Scheme, on the other hand, in the first place you always need to
432 include parentheses to force a function to be applied to arguments:
436 Moreover, there's a difference between ((M N) P) and (M N P). And each
437 of those are different from ((M) N P). Scheme differentiates between
438 functions that take one argument, those that take zero arguments (these
439 are called "thunks"), and those that take more than one argument.
441 This is awkward for our pedagogy, especially when you play with lambda
442 calculus inside Scheme. We'll try to do some special tricks that will
443 let ((M N) P) and (M N P) come out in Scheme when you'd expect them to.
444 We'll tell you about this later.
449 Subject: Constants / predefined variables
452 #t and #f (Scheme uses # to start lots of special values, e.g. #\h)
456 Syntax for building compound values: '(2 . 3) or (cons 2 3) is a
457 pair; '(2 3) or (list 2 3) is a list. Other lists: '() or (list)
463 in OCaml most functions are written to the left of their
464 arguments, as in lambda and Scheme. But common arithmetic operations are
465 infix unless they're enclosed in parens. So you'd write:
469 (Note: if you do this, best to always write ( + ) not (+). Sometimes it
470 doesn't matter but sometimes it does because of a language design
473 lists: [2; 3] others: []
479 Some lambda calculi do have constants, such as numbers. But mainstream
482 If you want boolean values, or numbers, or ordered pairs, or anything,
483 you'll have to make them by hand out of the raw stuff of the lambda
487 How do we build our own?
488 We'll start with boolean values
489 Next we'll do pairs, triples, and so on
490 = possibly type-heterog collections, of a specific length >= 2
491 Next class we'll do numbers
493 = ordered type-homogeneous collections permitting repetition,
494 of arbitrary length >= 0
496 Building multisets = unordered type-homog collections permitting rep
497 sets = unordered type-homog collections without rep
498 is harder. In these languages, functions are quite basic, ordered
499 pairs are harder, sets harder yet. Inverts the usual conceptual order.
504 if B is a boolean value (simple or syntactically complex), and IFTRUE
505 and IFFALSE are any two other, arbitrary expressions, we want:
508 to evaluate either to IFTRUE or to IFFALSE (depending on which boolean
513 should evaluate to Y.
515 The boolean constant true needs to be an expression such that:
517 always evaluate to X. How to do that?
519 Easy: define true to be: \x \y. x
520 Or more mnemonically: \t \f. t
527 If p is an ordered pair, we want it to accept a function of the form
528 (\x y. B) which does something with its component values.
532 should return the first member of p.
534 should return the sum of the members of p (assuming an appropriate
537 Note: `p (\x y. add x y)` could also be written as `p add`
541 Easy: define p to be (\f. f first_value second_value)
544 (\f. f first_value second_value) (\x y. B) is
545 (\x y. B) first_value second_value
547 Some comments here about CPS.
550 ----- End forwarded message -----
551 ----- Forwarded message from Jim Pryor <jim@jimpryor.net> -----
553 Date: Sun, 12 Sep 2010 20:13:46 -0400
554 From: Jim Pryor <jim@jimpryor.net>
555 To: Chris Barker <chris.barker@nyu.edu>
558 I've got some other notes pounding on the declarative / imperatival
559 difference, that I'd want to work into discussion preceding everything I
562 Other ideas I had for homework were just doing some beta-reductions and
563 so on. I can look for some Scheme exercises in Little Schemer or another
564 tutorial we've linked to. I'm sorry, I haven't really come up with much
565 more specific yet here.
569 I've got a pet peeve about the standard presentation of the grammar for
570 lambda calculus as this simple, three rule system. Oh and then by the
571 way here's also this unofficial shorthand. It's fine to give them that,
572 but I also want to mention you can just give a mildly more complex
573 grammar for what people really write. And we can point them to that. I
574 worked it out myself, quickly, and could have missed some cases, but I
575 think I have it. If you know of another statement of this, we could
576 cross-check it sometime.
578 I want to de-emphasize the role of alpha-conversion. It's perfectly reasonable to regard \x.x and \y.y as syntactically identical. I think Hankin has discussion of three ways to think about this, only one of which makes alpha-conversion any substantive transformation.
580 I don't mind mentioning eta-reduction, but I want to signal that it
581 makes a difference to the calculus whether that's permitted, say that
582 we'll be discussing it some later, and for now they shouldn't think much
586 Pedagogically I'd like to suppress eta-reduction by default, except when
587 we explicitly allow it.
590 ----- Forwarded message from Chris Barker <chris.barker@nyu.edu> -----