However in most implementations special-operator-p returns t for some
other symbols too. Eg. in SBCL
(let ((specops '()))
(do-all-symbols (s)
(when (special-operator-p s)
(push s specops)))
specops)
also includes SB-SYS:%PRIMITIVE.
Is SBCL's special-operator-p not ANSI compliant?
Helmut
Yes, but "3.1.2.1.2.2 Macro Forms" says:
An implementation is free to implement a Common Lisp special
operator as a macro. An implementation is free to implement any
macro operator as a special operator, but only if an equivalent
definition of the macro is also provided.
so the set of special-operator-p is not really fixed.
Moreover, what 3.1.2.1.2.1 says is that the intersection between the
special operators and COMMON-LISP is fixed, not that the set of the
special operators provided by an implementation is fixed.
Do not make the error of believing that implementations are identical
to Common Lisp!
--
__Pascal Bourguignon__ http://www.informatimago.com/
> Yes, but "3.1.2.1.2.2 Macro Forms" says:
>
> An implementation is free to implement a Common Lisp special
> operator as a macro. An implementation is free to implement any
> macro operator as a special operator, but only if an equivalent
> definition of the macro is also provided.
>
> so the set of special-operator-p is not really fixed.
So eg. DEFUN could also be a special operator in a ANSI compliant
implementation?
Helmut
Yes, absolutely - as long as there is also a macro definition available
for it as well.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
> Definitely! (As long as a macro is still provided).
In case this is not clear, the aim of this is that a program which
processes CL programs can do so by only knowing about the set of
special operators defined by CL. So, such a program would need to know
how to deal with CL:IF, but could rely on there being a macro expansion
for CL:COND (even if the implementation actually treated CL:COND as a
special operator).
--tim
It seems a bit pointless, though. E.g. the macro for our non-standard
special operator DEFUN could expand to a function call with the arglist
and body as quoted arguments:
(macroexpand '(defun foo () 48)) => (mystery-function 'foo '() '(48))
The implementation could still claim that the expansion is equivalent
but the processesing tool has no idea what the mysterious function does
with the quoted arguments. Even if the tool had access to the source of
the function.
Helmut
Sure, but at least the processing tool knows that all arguments to a
function are always evaluated, which is what a processing tool is
typically interested in, and which is what you can only infer from the
specification in the case of a special operator. If there is a macro
definition available, you don't have to guess what it does...
> The implementation could still claim that the expansion is equivalent
> but the processesing tool has no idea what the mysterious function does
> with the quoted arguments. Even if the tool had access to the source of
> the function.
But it knows the one thing that a code walker really needs to know:
what the evaluation rules are. If it gets to something which is just a
function call it knows, for instance, that no bindings are being made
or anything like that, whereas if it gets to, say, LET, it knows that
bindings *are* being made, and what those bindings are.
For this function, this expansion could be accepted, because the body
is a literal.
However the implementation is obliged to provide expansions that are
semantically correct.
In the case of a form such as:
(let ((a 1))
(defun f (x)
(+ a x)))
it couldn't expand the defun to (mystery-function 'f '(x) '((+ a x)))
because it transforms code into data, masking it from the code walker.
At the very least, it would have to expand to:
(mystery-function 'f '(x) (lambda () (+ a x)))
but this is wrong because now x comes out of the blue. So it would
have to be:
(mystery-function 'f '(x) (lambda (x) (block f (+ a x))))