[untitled]

    ; The Y Combinator
    ; ----------------

    ; The Y combinator is defined as follows:

    (define Y
        (lambda (f)
            (
                (lambda (x)
                        (f (lambda (y) ((x x) y)))
                )
                (lambda (x)
                        (f (lambda (y) ((x x) y)))
                )
            )
        )
    )

    ; It has the property that (Y f) is equivalent to (f (Y f)) (and so to
    ; infinity. One can use the Y combinator to implement recursion in
    ; lambda calculus.

    ; Let's see an example in Scheme on how to use the Y combinator:

    (define (top x) (car x))
    (define (var x) (cadr x))        ; (cadr x) is equivalent to (car (cdr x))
    (define (result x) (caddr x))

    ; This function calculates the sum of integers from (var x) to (top x).
    ; Note that we can only pass one argument to the Y's function so a
    ; list is used to pass multiple arguments.
    (define mysum
        (Y (lambda (f)
            (lambda (x)
                (if (<= (var x) (top x))
                    ; If part
                        ; The Y combinator enables us to use f to call
                        ; itself recursively.
                    (f (list
                        (top x)
                        (+ (var x) 1)
                        (+ (result x) (var x))
                    ))
                    ; Else part
                    x
                )
            )
        ))
    )

    (define solution (mysum (list 10 5 0)))
    (display "The solution is: ")
    (display (result solution))
    (newline)

    ; Naturally, we can convert this entire thing to lambda calculus:

    (define (top x) (lc_car x))
    (define (var x) (lc_car (lc_cdr x)))
    (define (result x) (lc_car (lc_cdr (lc_cdr x))))

    (define make-mysum-list
    (lambda (top)
        (lambda (var)
            (lambda (result)
                ((lc_cons top) ((lc_cons var) ((lc_cons result) zero)))
            )
        )
    ))

    ; Notice that we wrap the inner if's in lambdas and pass zero as no_use.
    ; Otherwise, both conditional clauses will always be evaluated and it will
    ; run an infinite number of times.
    (define mysum
        (Y (lambda (f)
            (lambda (x)
                (((((less-or-equal (var x)) (top x)) ; If var x < top x
                    ; If part
                    (lambda (no_use)
                        (f
                            (((make-mysum-list
                                (top x))
                                (succ (var x)))
                                ((add (result x)) (var x))
                            )
                        )
                    ))
                    ; Else part
                    (lambda (no_use)
                        x
                    ))
                        zero ;  Pass zero as argument to no_use
                )
            )
        ))
    )

    (define solution (mysum
        (((make-mysum-list
            (int->church 10))
            (int->church 5))
            (int->church 0))
            ))

    (display "The solution is: ")
    (display (church->int (result solution)))
    (newline)