Lisp-1 vs Lisp-2
The Lisp family of languages is relatively new to me. I learned both Clojure and Emacs Lisp at the same time, as Emacs is a popular Clojure editor. Learning these two lisps side by side has made me wonder about the subtle differences between the two, in particular how they approach passing functions as arguments to other functions (first class functions). It turns out this boils down to Clojure being a lisp-1 and Emacs Lisp a lisp-2.
Clojure is a lisp-1, meaning it uses the same name resolution for both functions and value bindings. This makes passing functions as arguments to other functions simple.
(defn my-apply [f arg1 arg2] (f arg1 arg2)) (my-apply + 2 2) => 4
The downside of this is that local functions and values can "shadow" existing functions.
(def f -) (defn my-apply [f arg1 arg2] (f arg1 arg2)) (f 2 2) => 0 (my-apply + 2 2) => 4
Emacs Lisp on the other hand is a lisp-2, meaning it has different name resolution for functions and value bindings. You can't just pass the function as an argument.
(defun my-apply (f arg1 arg2) (f arg1 arg2)) (my-apply + 2 2) => Symbol's value as variable is void: +
You have to quote the function first.
(defun my-apply (f arg1 arg2) (f arg1 arg2)) (my-apply '+ 2 2) => Symbol's function definition is void: f
The function then needs to be called using the
(defun my-apply (f arg1 arg2) (funcall f arg1 arg2)) (my-apply '+ 2 2) => 4
This prevents functions shadowing values but at the cost of making the mechanism of passing functions as arguments more complex.
Hopefully this post helps shed some light on the differences between lisp-1 and lisp-2. For a more thorough discussion checkout this paper.