2008-12-14

1 namespace to rule them all

This thing scares and confuses me: filter even [1..10]
Is even a function or a var?
Personally I'd prefer: filter #'even [1..10]

Common Lisp's n-namespace property is one of the most underestimated features of this most underestimated language. In CL you virtually always know, what you are dealing with, a variable or a function. "Phew!" you say, "in C++ as well". Not so fast. If you try to use callbacks you don't. And when we enter the realm of the functional paradigm, where functions fly all around like daggers in the infamous house, it's really good to know for sure.

Let's restate the rules:
1. Prefix notation: in first position of a form should always be a name of a function/macro/special operator (unless it's an inner form of a macro, which introduces its own structure). So:
* (+ 1 2), not (1 + 2)
* (print 1) -- just like print(1)
* (with-open-file (in "test.txt") ...) -- a structural macro

2. If you want to pass a function somewhere #' is your best friend. Thus you can (fun)call it, apply it, map/filter with it etc.

3. Finally we need to add one more ingredient to the recipe -- the ability to use (lambda ...) forms in function position. We can do it with such a reader macro:
(set-dispatch-macro-character #\# #\f
(lambda (stream subchar arg)
(declare (ignore subchar)
(ignore arg))
(let ((sexp (read stream t nil t)))
(let ((fname (gensym)))
(setf (symbol-function fname) (eval `(lambda ,@sexp)))
fname))))

which allows us to write this code:
CL-USER> (#f((a b) (+ a b)) 1 2)
3

No comments:

Post a Comment