setq x setf

24 views
Skip to first unread message

glauber

unread,
Jun 14, 2000, 3:00:00 AM6/14/00
to
OK, really stupid novice question of the day...

What's the difference between setq and setf? Both of them seem
to set up variables. For example (using Clisp):

[69]> (setf hello 'world)
WORLD
[70]> (setq foo 'bar)
BAR
[71]> hello
WORLD
[72]> foo
BAR


My current idea is that setq applies to variables only, while
setf can apply to other things such as objects. (???)

Again, apologies for the simplicity of the question. I couldn't
figure it out from the Common Lisp spec, or from CLtL2.


glauber

* Sent from RemarQ http://www.remarq.com The Internet's Discussion Network *
The fastest and easiest way to search and participate in Usenet - Free!


Tunc Simsek

unread,
Jun 14, 2000, 3:00:00 AM6/14/00
to
Setf is more general. You can setf a setfable function:

(defclass c ()
((x :accessor x)))

(setq i (make-instance 'c))
(setf (x i) 1)

glauber

unread,
Jun 14, 2000, 3:00:00 AM6/14/00
to
Thanks to all who replied.

Just one more question in this thread:

is it OK then to use setf to set variables too, or is there any
advantage to using setq? (performance, maybe?)

Xenophon Fenderson the Carbon(d)ated

unread,
Jun 14, 2000, 3:00:00 AM6/14/00
to
>>>>> "glauber" == glauber <glauber.rib...@experian.com.invalid> writes:

glauber> My current idea is that setq applies to variables only,
glauber> while setf can apply to other things such as
glauber> objects. (???)

SETF applies to "generalized places". For instance, a location within
an array (as by the accessor AREF) is a place, so to set it, you use:
(SETF (AREF array index1 ...) newvalue)

Cf. section 5.1 "Generalized Reference" in the HyperSpec
(http://www.xanalys.com/software_tools/reference/HyperSpec/Body/sec_5-1.html),
as well as the glossary entries for "generalized reference"
(http://www.xanalys.com/software_tools/reference/HyperSpec/Body/glo_g.html#generalized_reference)
and "place"
(http://www.xanalys.com/software_tools/reference/HyperSpec/Body/glo_p.html#place)

For symbols, it just so happens that

(SETF FOO 1)

and

(SETF (SYMBOL-VALUE 'FOO) 1)

are the same thing, largely because

FOO

and

(SYMBOL-VALUE 'FOO)

are the same thing.

(SET (QUOTE FOO) 1) and (SETQ FOO 1) are the same thing; SETQ expands
into the SET function, and SET changes the SYMBOL-VALUE of the symbol.

You should probably also take a look at the examples in function
documentation for SET
(http://www.xanalys.com/software_tools/reference/HyperSpec/Body/fun_set.html),
as well as read the macro documentation for SETF
(http://www.xanalys.com/software_tools/reference/HyperSpec/Body/mac_setfcm_psetf.html).

Hope this helps!

--
"I will never submit to your lustful advances", cried Princess Beatrice, as the
wealthy, powerful, muscular and strikingly handsome Count Bertrand slowly
adjusted his mink gloves, "at least for another half-hour!"
--Dr. Zinn, from the novel

Paul Foley

unread,
Jun 14, 2000, 3:00:00 AM6/14/00
to
On 14 Jun 2000 19:41:39 -0400, Xenophon Fenderson the Carbon(d)ated wrote:

> For symbols, it just so happens that

> (SETF FOO 1)

> and

> (SETF (SYMBOL-VALUE 'FOO) 1)

> are the same thing, largely because

> FOO

> and

> (SYMBOL-VALUE 'FOO)

> are the same thing.

> (SET (QUOTE FOO) 1) and (SETQ FOO 1) are the same thing; SETQ expands
> into the SET function, and SET changes the SYMBOL-VALUE of the symbol.

This is false. Symbols often (even _usually_) have values that are
not the same as the SYMBOL-VALUE. Try

(let ((x 42))
(symbol-value 'x))

and see whether you get 42 or an "unbound variable" error. [And if
you do get 42, try again in a real Lisp, instead of in Emacs...]

--
If that makes any sense to you, you have a big problem.
-- C. Durance, Computer Science 234
(setq reply-to
(concatenate 'string "Paul Foley " "<mycroft" '(#\@) "actrix.gen.nz>"))


Rainer Joswig

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <0f106a56...@usw-ex0102-016.remarq.com>, glauber
<glauber.rib...@experian.com.invalid> wrote:

> My current idea is that setq applies to variables only, while
> setf can apply to other things such as objects. (???)

SETF applies to "places".

If you want to develop datastructures, you usually need
a way to change parts of the datastructure and
a way to retrieve parts of the datastructure.
So you need a "getter" and a "setter".
Common Lisp tries to unify this view so that
you need only to know the getter - if the getter
forms a so called place, then you can use SETF
to change the content.

Example:

Array
- getter is AREF
(aref *an-array* index)
- setting is done via SETF
(setf (aref *an-array* index) new-value)

Objects
- getter for slots is SLOT-VALUE
(slot-value object 'slot-name)
- setting is done via SETF
(setf (slot-value object 'slot-name) new-value)

You can also define new SETF methods.

See http://www.xanalys.com/software_tools/reference/HyperSpec/Body/mac_setfcm_psetf.html

--
Rainer Joswig, BU Partner,
ISION Internet AG, Steinhöft 9, 20459 Hamburg, Germany
Tel: +49 40 3070 2950, Fax: +49 40 3070 2999
Email: mailto:rainer...@ision.net WWW: http://www.ision.net/

Rainer Joswig

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <0e31a7e5...@usw-ex0102-016.remarq.com>, glauber
<glauber.rib...@experian.com.invalid> wrote:

> Thanks to all who replied.
>
> Just one more question in this thread:
>
> is it OK then to use setf to set variables too, or is there any
> advantage to using setq? (performance, maybe?)

It's OK to use SETF. It depends on style:

- use the most specific Lisp facility, this makes
your intentions clear -> SETQ

- use general mechanisms, this reduces cognitive load, since
you have to remember less programming constructs -> SETF

Barry Margolin

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <0e31a7e5...@usw-ex0102-016.remarq.com>,
glauber <glauber.rib...@experian.com.invalid> wrote:
>Thanks to all who replied.
>
>Just one more question in this thread:
>
>is it OK then to use setf to set variables too, or is there any
>advantage to using setq? (performance, maybe?)

SETF is a macro that expands into whatever is appropriate for the
destination. (setf <var> <value>) will expand into (setq <var> <value>) at
compile time, so the behavior should be identical.

As the other poster said, it's purely a stylistic choice.

--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Paul Foley

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to

Philip Lijnzaad

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to

> (SET (QUOTE FOO) 1) and (SETQ FOO 1) are the same thing; SETQ expands
> into the SET function, and SET changes the SYMBOL-VALUE of the symbol.

But SET has been officially deprecated ...

Philip
--
Ban GM foods! Long live the Mesolithicum, pesticides and starvation
-----------------------------------------------------------------------------
Philip Lijnzaad, lijn...@ebi.ac.uk \ European Bioinformatics Institute,rm A2-24
+44 (0)1223 49 4639 / Wellcome Trust Genome Campus, Hinxton
+44 (0)1223 49 4468 (fax) \ Cambridgeshire CB10 1SD, GREAT BRITAIN
PGP fingerprint: E1 03 BF 80 94 61 B6 FC 50 3D 1F 64 40 75 FB 53

Erik Naggum

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
* glauber <glauber.rib...@experian.com.invalid>

| What's the difference between setq and setf?

setq is a special operator that takes a variable (binding, really)
and a value, and causes references to that variable (binding) after
the setq to yield the value.

setf is a macro that takes a place (generalized reference) and a
value, and causes references to the place after the setf to yield
the value, in ways appropriate for each place. It expands into setq
for variables (bindings), for instance.

#:Erik
--
If this is not what you expected, please alter your expectations.

Erik Naggum

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
* Xenophon Fenderson the Carbon(d)ated

| For symbols, it just so happens that
| (SETF FOO 1)
| and
| (SETF (SYMBOL-VALUE 'FOO) 1)
| are the same thing, largely because
| FOO
| and
| (SYMBOL-VALUE 'FOO)
| are the same thing.

This is just plain false.

| (SET (QUOTE FOO) 1) and (SETQ FOO 1) are the same thing; SETQ expands
| into the SET function, and SET changes the SYMBOL-VALUE of the symbol.

This is just plain false, too.

Tim Bradshaw

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
* glauber wrote:
> is it OK then to use setf to set variables too, or is there any
> advantage to using setq? (performance, maybe?)

I use SETF exclusively. There should not be any performance
difference -- SETF will macroexpand to SETQ in the simple cases.

--tim

Xenophon Fenderson the Carbon(d)ated

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
>>>>> "Paul" == Paul Foley <myc...@actrix.gen.nz> writes:

Paul> This is false. Symbols often (even _usually_) have values
Paul> that are not the same as the SYMBOL-VALUE. Try

Paul> (let ((x 42)) (symbol-value 'x))

Yup. In my zeal to answer I totally forgot about lexical bindings.

Erik Naggum

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
* Philip Lijnzaad <lijn...@ebi.ac.uk>

| But SET has been officially deprecated ...

I think this was a bad idea. I completely fail to appreciate some
of the deprecations -- most of them give me this icky Scheme feeling.

(remove-if-not <obvious-function> ...) is supposed to be inferior to
(remove-if (complement <obvious-function) ...)? I'm _so_ thrilled
with the double negative, already, I really need _complement_! And
(set <symbol> <value> is inferior to (setf (symbol-value ...) ...)?
Gimme a break!

Deprecation is a signal to the community that it needs to evaluate
its habits and signal the committee back if it deems them valid.
For instance, there's no doubt that :test and :test-not had fuzzy
semantics when combined and non-trivial prophylaxis, but that
doesn't mean the *-if-not functions suffer similarly fuzziness.

I use set when I actually have symbols that I don't _want_ to be
some general data structure. Symbols are special animals in many
ways, and I don't want to bury that in a "call" to symbol-value.

#:Erik, ¢2

Paul Dietz

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <BTV15.98$Nf7.2276@burlma1-snr2>,
Barry Margolin <bar...@genuity.net> wrote:

> SETF is a macro that expands into whatever is appropriate for the
> destination. (setf <var> <value>) will expand into (setq <var> <value>) at
> compile time, so the behavior should be identical.

Nitpick: in theory, yes, in practice there can be a trivial but
nonzero difference in some implementations.

For example, if *x* is a global variable then the forms

(setq *x* t)

and

(setf *x* t)

compile to different code in ACL 5.0.1 (this is because the SETF macro
inserts a temporary variable in the second case and does not propagate
the T forward in a way that lets the compiler figure out that no write
barrier is needed.)

Paul

Erik Naggum

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
* Paul Dietz

| Nitpick: in theory, yes, in practice there can be a trivial but
| nonzero difference in some implementations.

If practice differs from theory, you have found a bug. Report bugs
as bugs to be removed, not as some nasty thing programmers need to
be made _aware_ of. Sheesh! Such is the worst of all possible ways
to deal with problems. If you don't get a fix within a reasonable
amount of time and the bug causes you to have to circumvent good
engineering decisions and write bad code that increases the overall
complexity of the system and introduces portability and maintenance
issues that are otherwise unwarranted, complain _vociferously_.
Accept no substitute for fixes to demonstrable bugs!

(Well, in this here day and age, one _acceptable_ "substitute" for
fixes to other people's mistakes is a reduced purchase price of the
buggy product, such as you getting the source code and assuming full
responsibilit for any problems. To some of us, that is unworkable.)

| For example, if *x* is a global variable then the forms (setq *x* t)

| and (setf *x* t) compile to different code in ACL 5.0.1 ...

I have been unable to reproduce this as stated.

#:Erik

Barry Margolin

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <31700592...@naggum.no>, Erik Naggum <er...@naggum.no> wrote:
>* Philip Lijnzaad <lijn...@ebi.ac.uk>
>| But SET has been officially deprecated ...
>
> I think this was a bad idea. I completely fail to appreciate some
> of the deprecations -- most of them give me this icky Scheme feeling.
...

> I use set when I actually have symbols that I don't _want_ to be
> some general data structure. Symbols are special animals in many
> ways, and I don't want to bury that in a "call" to symbol-value.

SET was deprecated in favor of SETF of SYMBOL-VALUE. You can still do what
you want to do, we're just encouraging you to use a more "modern" syntax.

I think the feeling was that this isn't such a common thing that we really
need two ways to do it in the language. 30 years ago SETF and DEFSTRUCT
didn't exist, and SET was pretty commonly used, but it's now a relic and
not deserving of such a privileged status.

On the other hand, we didn't deprecate SETQ in favor of SETF because SETQ
is used pervasively. Making everyone globally replace all their SETQ's
with SETF's would be horrible.

Philip Lijnzaad

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to

Erik> * Philip Lijnzaad <lijn...@ebi.ac.uk>
Erik> | But SET has been officially deprecated ...

Erik> I think this was a bad idea. I completely fail to appreciate some
Erik> of the deprecations -- most of them give me this icky Scheme feeling.

I have no real experience with this, but would find

(setf (symbol-value sym) val)

much much clearer than

(set sym val)

The first form signals to me that something not entirely usual is going on;
the latter looks more like a nasty-to-spot typo. Like it's kinda clearer to
see

(funcall (hi-order-func args) more-args)

than

((hi-order-func args) more-args)

, really.

Erik> Gimme a break!

uh, yes, I was going to: what happened to all your lowercase sentence
beginnings ?-)

Sashank Varma

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <0e31a7e5...@usw-ex0102-016.remarq.com>, glauber
<glauber.rib...@experian.com.invalid> wrote:

[snip]


>is it OK then to use setf to set variables too, or is there any
>advantage to using setq? (performance, maybe?)

[snip]

i use SETQ on the principle that using the most specific construct
best communicates intent.

then again, i use (SETF (CAR ...) ...) and (SETF (CDR ...) ...)
rather than RPLACA and RPLACB, so take my advice with a grain of
salt!

sashank

Sashank Varma

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <aT625.10$4p1.258@burlma1-snr2>, Barry Margolin
<bar...@genuity.net> wrote:

[snip]


>SET was deprecated in favor of SETF of SYMBOL-VALUE. You can still do what
>you want to do, we're just encouraging you to use a more "modern" syntax.
>
>I think the feeling was that this isn't such a common thing that we really
>need two ways to do it in the language. 30 years ago SETF and DEFSTRUCT
>didn't exist, and SET was pretty commonly used, but it's now a relic and
>not deserving of such a privileged status.
>
>On the other hand, we didn't deprecate SETQ in favor of SETF because SETQ
>is used pervasively. Making everyone globally replace all their SETQ's
>with SETF's would be horrible.

since SETF is a macro, it has to expand into an expression.
i assume that implementations ensure that this expansion is
pure ANSI CL; this may even be mandated in the standard.

so, (SETF (SYMBOL-VALUE ...) ...) is probably expanded in
the following way in all implementations:
? (macroexpand '(setf (symbol-value '*a*) 5))
(SET '*A* 5)
T
?
does this imply that SET will never disappear, then, for
if it did, SETF would have no ANSI CL construct to expand to
(i.e., one that modifies dynamic bindings)?

the same logic seems to imply that, the pervasiveness of
SETQ aside, it will never go away because (SETF <symbol> ...)
will always require it for expansion purposes.

is this right? one way that i could be wrong is that it
could be perfectly legal for SETF to macroexpand into
implementation-specific mechanisms for modifying bindings,
but this just seems wrong.

sashank

Barry Margolin

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <sashank-1506...@129.59.212.53>,

Sashank Varma <sas...@vuse.vanderbilt.edu> wrote:
>does this imply that SET will never disappear, then, for
>if it did, SETF would have no ANSI CL construct to expand to
>(i.e., one that modifies dynamic bindings)?

If SET disappears, it can expand into

(funcall #'(setf set) 5 '*A*)

or

(SYSTEM-INTERNAL::SET-SYMBOL-VALUE '*A* 5)

>is this right? one way that i could be wrong is that it
>could be perfectly legal for SETF to macroexpand into
>implementation-specific mechanisms for modifying bindings,
>but this just seems wrong.

This is the case. Consider that there are no standard expressions for SETF
of the following accessors to expand into: GETHASH, DOCUMENTATION,
FILL-POINTER, SYMBOL-FUNCTION, SYMBOL-PLIST, MACRO-FUNCTION. Historically,
accessors inherited from Maclisp have standard setter function, since
Maclisp didn't have SETF as a built-in feature and the setters were
retained for compatibility (the property list functions are an exception, I
don't know why compatibility for them was dropped), but accessors inherited
from Zetalisp or introduced by the Common Lisp designers do not since
there's no compatibility requirement.

Erik Naggum

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
* sas...@vuse.vanderbilt.edu (Sashank Varma)

| since SETF is a macro, it has to expand into an expression.
| i assume that implementations ensure that this expansion is
| pure ANSI CL; this may even be mandated in the standard.

Why do you assume that? Why should it be mandated?

| one way that i could be wrong is that it could be perfectly legal
| for SETF to macroexpand into implementation-specific mechanisms for
| modifying bindings, but this just seems wrong.

Could you elaborate on why you think this way?

Barry Margolin

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
In article <31700980...@naggum.no>, Erik Naggum <er...@naggum.no> wrote:
>* sas...@vuse.vanderbilt.edu (Sashank Varma)
>| since SETF is a macro, it has to expand into an expression.
>| i assume that implementations ensure that this expansion is
>| pure ANSI CL; this may even be mandated in the standard.
>
> Why do you assume that? Why should it be mandated?

Assumptions don't have reasons. If they did, they would be conclusions,
not assumptions.

Steven M. Haflich

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
Erik Naggum wrote:
>
> * sas...@vuse.vanderbilt.edu (Sashank Varma)
> | since SETF is a macro, it has to expand into an expression.
> | i assume that implementations ensure that this expansion is
> | pure ANSI CL; this may even be mandated in the standard.
>
> Why do you assume that? Why should it be mandated?
>
> | one way that i could be wrong is that it could be perfectly legal
> | for SETF to macroexpand into implementation-specific mechanisms for
> | modifying bindings, but this just seems wrong.

It is perfectly legal for setf expansions to use implementation-specific
mechanisms. Indeed, it is logically necessary in those cases where
there is no specified mechanism in the standard for performing a
specified operation. For example, as has been pointed out, setf of
fill-pointer _must_ expand into something not specified in the ANS since
the ANS specifies nothing that will do the job.

BUT any such implementation-specific mechanism _must_ be (or eventually
macroexpand into) a call to an implementation function. No implementation
setf expansion, nor for that matter any other standard macro, may expand
into a nonstandard special form. To do so would make it impossible for
portable code walkers to work, and that would be a bad thing.

Compilers are free to treat additional operators as special forms, but
they must provide real macro or function versions for benefit of other
code walkers that they themselves may ignore in favor of some semantically
equivalent special form.

Xenophon Fenderson the Carbon(d)ated

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
>>>>> "Erik" == Erik Naggum <er...@naggum.no> writes:

Erik> This is just plain false.

I was thinking only of the top-level, and in my eagerness to post
(since I enjoy trying to be helpful), I was a dumb-ass and forgot about
lexical bindings. Unless SYMBOL-VALUE and the top-level symbol
binding are different things, so if I'm still confused about this
issue, please correct me.

Sashank Varma

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to

>Erik Naggum wrote:
>>
>> * sas...@vuse.vanderbilt.edu (Sashank Varma)
>> | since SETF is a macro, it has to expand into an expression.
>> | i assume that implementations ensure that this expansion is
>> | pure ANSI CL; this may even be mandated in the standard.
>>
>> Why do you assume that? Why should it be mandated?

thankfully i've been saved from publicly fumbling too much
around an incorrect assumption.

[snip]


>BUT any such implementation-specific mechanism _must_ be (or eventually
>macroexpand into) a call to an implementation function. No implementation
>setf expansion, nor for that matter any other standard macro, may expand
>into a nonstandard special form. To do so would make it impossible for
>portable code walkers to work, and that would be a bad thing.

[snip]

you nailed the thing that was bugging me -- could program-analyzing
programs work across implementations if ansi cl macros are allowed to
expand into implementation-specific "mechanisms"? the answer, as i now
see, is "of course" -- provided those mechanisms bottom-out as function
calls or ansi-cl-specified special operators.

makes sense in retrospect.

sashank.

Erik Naggum

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
* sas...@vuse.vanderbilt.edu (Sashank Varma)
| since SETF is a macro, it has to expand into an expression.
| i assume that implementations ensure that this expansion is
| pure ANSI CL; this may even be mandated in the standard.

Why do you assume that? Why should it be mandated?

| one way that i could be wrong is that it could be perfectly legal


| for SETF to macroexpand into implementation-specific mechanisms for
| modifying bindings, but this just seems wrong.

Could you elaborate on why you think this way?

Erik Naggum

unread,
Jun 16, 2000, 3:00:00 AM6/16/00
to
* Barry Margolin <bar...@genuity.net>

| Assumptions don't have reasons.

Sigh. "Why" does not only refer to reasons, regardless of the truth
of your statement, but to any cause, as in "how come". Perhaps your
assumptions are causeless and entirely random, but this is not a
universal truth.

Barry Margolin

unread,
Jun 16, 2000, 3:00:00 AM6/16/00
to
In article <39499071...@pacbell.net>,

Steven M. Haflich <s...@alum.mit.edu> wrote:
>Compilers are free to treat additional operators as special forms, but
>they must provide real macro or function versions for benefit of other
>code walkers that they themselves may ignore in favor of some semantically
>equivalent special form.

While this is a good idea, and I even think there was some discussion of
the issue in X3J13, did we actually put anything into the standard that
specifies it? It says that there's no way for the *user* to define new
special operators, but doesn't say that the implementor can't build in more
(and even the clause that says that there's no way for the user to define
them presumably means that there's no *standard* way to do so -- it can't
stop the implementor from providing an extension that the user could
invoke). It also says that any macro operator can be implemented as a
special operator as long as the macro definition is still there, but that's
not talking about new special operators that the implementation defines (I
think it's actually referring to the operators that the standard says are
macros).

The problem with saying that all implementation-defined special operators
have to have macro definitions as well is what the macro could expand into?
The implementation presumably defined these special operators because they
do something that can't be done using macros or functions (I'm ignoring
operators implemented specially just for optimization reasons); for
instance, suppose the CL designers had decided not to include TAGBODY and
GO in the language, but a vendor wanted to provide a Maclisp-compatible
version of PROG that included these features -- what would they expand
into? The SPECIAL-OPERATOR-P function is provided so that code walkers can
notice when they've stumbled onto implementation-dependent special forms;
if they don't know how to handle that special form, they can punt and
report the failure to the user.

Steven M. Haflich

unread,
Jun 17, 2000, 3:00:00 AM6/17/00
to

Barry Margolin wrote:
>
> In article <39499071...@pacbell.net>,
> Steven M. Haflich <s...@alum.mit.edu> wrote:
> >Compilers are free to treat additional operators as special forms, but
> >they must provide real macro or function versions for benefit of other
> >code walkers that they themselves may ignore in favor of some semantically
> >equivalent special form.
>
> While this is a good idea, and I even think there was some discussion of
> the issue in X3J13, did we actually put anything into the standard that
> specifies it? It says that there's no way for the *user* to define new
> special operators, but doesn't say that the implementor can't build in more
> (and even the clause that says that there's no way for the user to define
> them presumably means that there's no *standard* way to do so -- it can't
> stop the implementor from providing an extension that the user could
> invoke).

An implementation may have extensions, to be sure, but as soon as one is
invoked the resulting world _might_ no longer be ANS conformant. But in any
case, this is what the ANS says:

3.1.2.1.2.1
The set of special operator names is fixed in Common Lisp; no way is provided
for the user to define a special operator. The next figure lists all of the
Common Lisp symbols that have definitions as special operators.

26.1.19
special operator:
n. one of a fixed set of symbols, enumerated in Figure 3.1.2.1.2.1 Special
Forms, that may appear in the car of a form in order to identify the form as
a special form.

> It also says that any macro operator can be implemented as a
> special operator as long as the macro definition is still there, but that's
> not talking about new special operators that the implementation defines (I
> think it's actually referring to the operators that the standard says are
> macros).

I take this to mean that the compiler does not need to use the macroexpansion
if for some reason it wants to use the special form. One such example in ACL
is the treatment of a top-level defun. The file compiler recognizes these
and generates various load-time effects in a way more efficient than what the
macroexpansion would generate. (Compiled files are smaller and load faster.)
But the observed effects are very carefully kept equivalent, and I personally
placed strong comments in the code warning future developers to keep things
that way.

> The problem with saying that all implementation-defined special operators
> have to have macro definitions as well is what the macro could expand into?
> The implementation presumably defined these special operators because they
> do something that can't be done using macros or functions (I'm ignoring
> operators implemented specially just for optimization reasons); for
> instance, suppose the CL designers had decided not to include TAGBODY and
> GO in the language, but a vendor wanted to provide a Maclisp-compatible
> version of PROG that included these features -- what would they expand
> into?

I could still implement it grotesquely (and inefficiently, but not grossly
so) using catch/throw, case, and tail-position call elimination. I _think_
it can be done without dependency on tail-call elimination, but I'm too
lazy to think though the implementation right now.

> The SPECIAL-OPERATOR-P function is provided so that code walkers can
> notice when they've stumbled onto implementation-dependent special forms;
> if they don't know how to handle that special form, they can punt and
> report the failure to the user.

But that would mean that no code could depend upon the success of a code
walker. That seems a poor design, similar to C++. The reason Lisp has
code walkers is so tools that were not designed to interoperate can still
do so. The Java VM tries to accomplish this with load/run time mechanisms.
Lisp accomplishes this at compile/load/run time. The purposes and tradeoffs
are different.

Reply all
Reply to author
Forward
0 new messages