Hacker News new | ask | show | jobs
by nils-m-holm 2498 days ago
Lambda Calculus (LC) versus LISP is not just about lexical scoping, but also about partial application (currying), which is cumbersome in LISP and natural in LC. In LC (where \ = lambda)

    (\xy.x)M  ==>  \y.M
while in LISP

    ((lambda (x y) x) M)  ==>  undefined
because the lambda function expects two arguments. Of course

\xy.x is just an abbreviation for \x.\y.x, so the LISP counterpart would really be

    ((lambda (x) (lambda (y) x)) M)  ==>  (lambda (y) M)
but this only proves the point that currying is natural in LC and not in LISP, because LC provides syntactic sugar that allows to treat higher-order functions and functions of multiple variables in the same way.

Also, LC is not compatible with functions with a variable number of arguments, which is common in LISP. For instance,

    (+ 1)  ==>  1
in most LISPs, but given PLUS == \mnfx.mf(nfx) and 1 == \x.fx

    PLUS 1  ==>  \nfx.f(nfx) == SUCC
i.e., (PLUS 1) reduces to "SUCCessor", the function adding one to its argument.

In most LISP dialects, you can pass any number of arguments to a variable-argument function like +. So what does the syntax (F X) denote in general? The application of a unary function to one argument or the partial application of a binary function? Or a ternary one...?

In LC it does not matter, because multi-variable functions and higher-order functions are the same.

I have developed a LISPy language that uses currying instead of functions of multiple arguments in the book Compiling Lambda Calculus (https://www.t3x.org/clc/index.html).

You can download the code here: https://www.t3x.org/clc/lc1.html.