Search code examples
functioncommon-lispspecial-form

How is "+" Implemented in Common Lisp Using Special Operators/Forms


In On Lisp (page 9), one can find the following claim:

Functions are the building-blocks of Lisp programs. They are also the building-blocks of Lisp. In most languages the + operator is something quite different from user-defined functions. But Lisp has a single model, function application, to describe all the computation done by a program. The Lisp + operator is a function, just like the ones you can define yourself. In fact, except for a small number of operators called special forms, the core of Lisp is a collection of Lisp functions. What’s to stop you from adding to this collection? Nothing at all: if you think of something you wish Lisp could do, you can write it yourself, and your new function will be treated just like the built-in ones.

My question is how exactly would something like a + operator be implemented using the following special operators? Or are there actually more operators being used and Graham is just being imprecise and dramatic?

block      let*                  return-from      
catch      load-time-value       setq             
eval-when  locally               symbol-macrolet  
flet       macrolet              tagbody          
function   multiple-value-call   the              
go         multiple-value-prog1  throw            
if         progn                 unwind-protect   
labels     progv                                  
let        quote    

Is there a way to see source code for these functions?


Solution

  • He's not saying every function is implemented in terms of these special forms.

    He's saying + (like every other function) is a function:

    • It can be called using the normal syntax (+ x y z) (where + is the function and x, y, z the arguments).
    • The arguments will be evaluated first: (f (g) (h)) will call both g and h before calling f, even if f happens to be +.
    • You can pass it around like any other function and call it through funcall and apply: (let ((x #'+)) (funcall x 1 2 3)) is 6.

    The point is that these properties do not necessarily hold for special forms. if does not evaluate all of its arguments first; you can't take a reference to let and call it indirectly; etc.

    Of course that still leaves the door open for "compiler magic". At some point + has to perform low-level operations that depend e.g. on how numbers are implemented. The details will look different depending on your Lisp compiler.