Adrian Kubala <adrian@sixfingeredman.net> wrote:
+---------------
| Macros DO let you implement your own evaluation rules, but only by
| virtue of the underlying special forms. If macros could only expand to
| function applications, then they would not be able to do this. So that's
| why you can implement if as a macro in terms of cond, or visa versa, but
| you can't implement either without some lower-level special form. At the
| very least, lambda must be a special form, musn't it?
+---------------
LAMBDA and QUOTE, I think, and in Common Lisp, probably FUNCTION as well.
And LOAD-TIME-VALUE, for nice compilation.
Of course, you need primitve *functions* such as FUNCALL & APPLY & C[AD]*R
and arithmetic and so forth, but I think the above list are the minimum
of special forms. You also need functional forms for "setters" for all
the common data types that don't already have them, e.g. AREF! (to use
the Scheme convention), which in CMUCL is LISP::%ASET and in CLISP is
SYSTEM::STORE.
You can even do away with IF (or COND) if you have a primitive function,
say, TRUTH-NUMBER, that takes a Lisp value and returns the fixnum 0 for
true and 1 for false [or vice-versa, it doesn't matter, either can be
made to work] and arrays and accessors [as above], like so:
(defmacro if (boolean consequent alternate)
`(funcall (aref (load-time-value
(make-array 2 :initial-contents
(list (lambda () ,consequent)
(lambda () ,alternate)))))
(truth-number ,boolean)))
[Note: The LOAD-TIME-VALUE isn't cheating, only an efficiency hack.
You can do the same thing without it, though with a lot more consing...]
Hmmm... Though looking back at the discussion we has about this a
year ago, it looks like there are a *LOT* more mandatory special
forms in Common Lisp than in Scheme:
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
PROGN, LET, LET*, and FLET (maybe) can be hacked with FUNCALL & LAMBDA.
Even LABELS can be hacked with the Y operator (ugh!). SETQ can be hacked
with an appropriate set of macros and low-level setters.
But BLOCK, TAGBODY, GO, UNWIND-PROTECT, MULTIPLE-VALUE-CALL, RETURN,
RETURN-FROM, etc., I dunno. I think you're in trouble there. And you
*can't* do EVAL-WHEN in a macro, can you? And then all the declaration
stuff -- DECLAIM, DECLARE, LOCALLY, THE -- those are pretty "special"
operators.
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607