[untitled]

    ; Notes
    ; -----

    ; 1. In this lecture, we have used "define" to define commonly used
    ; functions. However, we can write the whole program with all the functions
    ; defined by such constructs:

    (
        (lambda (succ)
            (
                ;;; Do something with succ - for example:
                (succ (lambda (f) (lambda (x) (f (f (f x))))))
            )
        )
        ; This is the definition of succ that is accepted as a value to the
        ; function call.
        (lambda (n)
                (lambda (f)
                    (lambda (x)
                            (f ((n f) x))
                    )
            )
        )
    )

    ; 2. Representing arrays: arrays (a.k.a vectors) can be constructed using
    ; a binary tree complex of pairs whose leaves are the array's values.

    ; 3. Church Numerals are base-1 numbers so they are not very efficient. If
    ; you strive for calculation efficiency in lambda calculus you may wish
    ; to represent numbers as vectors of digits, and define calculations on them
    ; using Al-Khwarizmi's algorithms.

    ; 4. In order to do things like write to the screen, to files, or etc. You
    ; need to supply the lambda calculus program with stubs. That way, everything
    ; can be done in LC.

    ; 5. It was proved that every recursive function can be implemented in
    ; Lambda Calculus.

    ; 6. Lambda Calculus is fairly easy to write in languages that support lexical
    ; scoping and closures. For example: Scheme, Perl, Python and ML
    ; can all do LC without any special programming.

    ; In other languages, like C, Pascal, Assembly or Basic, one can implement
    ; Lambda Calculus using a stack. I don't remember the exact details, but it's
    ; possible.

    ; 7. One can define Y-like combinators that take functions of more than
    ; one argument (I mean (lambda (x) (lambda (y) ... ))). For example, the
    ; two-argument Y is:

    (define Y2
        (lambda (g)
            (
                (lambda (f)
                    (g (lambda (x) (lambda (y) (((f f) x) y))))
                )
                (lambda (f)
                    (g (lambda (x) (lambda (y) (((f f) x) y))))
                )
            )
        )
    )

    ; 8. Instead of using pairs one can use a three-object tuple, or a four object
    ; tuple, etc. For example, the definition of the three-item tuple functions
    ; are:

    (define lc-cons-tuple3
        (lambda (first)
            (lambda (second)
                (lambda (third)
                    (lambda (which)
                        (((which first) second) third)
                    )
                )
            )
        )
    )

    (define tuple3-get-first
        (lambda (tuple)
            (tuple (lambda (x) (lambda (y) (lambda (z) x))))
        )
    )

    (define tuple3-get-second
        (lambda (tuple)
            (tuple (lambda (x) (lambda (y) (lambda (z) y))))
        )
    )

    (define tuple3-get-third
        (lambda (tuple)
            (tuple (lambda (x) (lambda (y) (lambda (z) z))))
        )
    )

    ; 9. It is sometimes useful to make a lambda expression into a tuple in which
    ; its car is a Church numeral that denotes its type, and specifies whether
    ; the cdr is a tuple, a church numeral, a function, a vector, etc.

    ; 10. Lambda Calculus still has a certain degree of arbitrarity. For example:
    ; Church numerals could have been defined as:

    (define zero (lambda (x) (lambda (f) x)))
    (define one  (lambda (x) (lambda (f) (f x))))
    (define two  (lambda (x) (lambda (f) (f (f x)))))

    ; Etc.
    ; Or true could have been defined as false and false as true...