Tuesday, 14 January 2014

LFE, Lisp and Erlang

My LFE (Lisp Flavoured Erlang), here and here, is not a Lisp-1 but a Lisp-2 as I think this fits better with Erlang. Well, it is really a Lisp-2+ which I will explain in a moment.

What are Lisp-1 and Lisp-2? Richard P. Gabriel in his paper defined the two as follows:
Lisp-1 has a single namespace that serves a dual role as the function namespace and value namespace; that is, its function namespace and value namespace are not distinct. In Lisp-1, the functional position of a form and the argument positions of forms are evaluated according to the same rules. Scheme is a Lisp-1 dialect.
Lisp-2 has distinct function and value namespaces. In Lisp-2, the rules for evaluation in the functional position of a form are distinct from those for evaluation in the argument positions of the form. Common Lisp is a Lisp-2 dialect.

What does this mean? For example take the expression (f a). In Lisp-1 you take the value of f as the function to call with the value of a as the argument, while in Lisp-2 you take the function of f to call with the value of a as the argument; you don't use the value of f. In Lisp-2 if you want to use the value of f as a function, for example if it a local variable, you can't do this directly but need to do something like (funcall f a) to do this, which is how it is done in LFE.

Lisp-1 is generally considered more elegant and simpler to understand, so why not use it for LFE? Well, this is where the properties of Erlang and the BEAM step in.

In Erlang you can define many top-level functions with the same name but with different arities, for example f/1, f/2 and f/3. While it was not strictly necessary to be able to do this in LFE, it is a basic property of Erlang which I felt was necessary to handle. Lisp-1 is clearly one value/function per name so it is difficult to extend the concept in a clean way. If we allow a symbol to have many functions at the top-level it seemed natural to be able to do this for local symbols/variables as well.

So in LFE we can both many top-level functions with the same name but different arities like Erlang:

(defun f (x) x)
(defun f (x y) (+ x y))
(defun f (x y z) (+ x y z))

And we can also define many local functions with the same name but different arities:

(flet ((f (x) x)
       (f (x y) (+ x y))
       (f (x y z) (+ x y z)))
  (list (f 5) (f 5 6) (f 5 6 7)))

=> (5 11 18)

I felt this was easier to do in a clean way if LFE was a Lisp-2.

This is what I meant in the beginning when I said LFE is a Lisp-2+, it not only has separate value and function space but it also allows multiple function definitions for the same name. Like Erlang does.


No comments:

Post a Comment