[LISPWORKS][Common Lisp HyperSpec (TM)] [Previous][Up][Next]


Issue:             SETF-GET-DEFAULT

References: SETF of GET (CLtL-II p. 240)

SETF of GETF (CLtL-II p. 242)

SETF of GETHASH (CLtL-II p. 438)

Related issues: Issue PUSHNEW-STORE-REQUIRED


Edit history: V1, 12 Feb 1991, Sandra Loosemore

Problem description:

In the descriptions of SETF of GET, GETF, and GETHASH, it is stated

that the optional default argument is ignored by SETF. It is not

clear whether this means that the *subform* corresponding to the

default argument that is ignored, or only the *result* of evaluating

the subform. The behavior is distinguishable in situations where the

subform has observable side-effects.


Clarify that if the optional "default" argument is supplied in a call

to GET, GETF, or GETHASH appearing as a SETF place, that subform

is evaluated according to the normal left-to-right evaluation rules for

subforms of a SETF place. However, its value is ignored.


#1: (setf (get 'foo 'message (print "hello world"))

"goodbye, cruel world")

=> prints "hello world"

#2: (let ((x nil))

(setf (getf x 'message (print "hello world"))

"goodbye, cruel world"))

=> prints "hello world"

#3: (let ((x (make-hash-table :test #'eq)))

(setf (gethash 'message x (print "hello world"))

"goodbye, cruel world"))

=> prints "hello world"


Discarding the form corresponding to the default argument would be

inconsistent with the rule that subforms of a SETF place are

evaluated in left-to-right order.

Current Practice:

Lucid version 4.0 does tests 1 and 3 correctly but fails on test 2.

Allegro version 3.1 performs all three tests correctly.

Symbolics Genera reportedly fails at least test 2.

Cost to Implementors:


Cost to Users:


Cost of non-adoption:

Implementations will continue to differ for no good reason.

Performance impact:



The language specification is made more precise and consistent.


Making the language more consistent is a good thing.


Kent Pitman notes:

Btw, someone (I think it was Allan Wechsler at Symbolics), that it

should be permissible for:

(LET ((X '(A 1 B 2)))

(SETF (GETF X 'C 3) 3)


=> (A 1 B 2)

because what the SETF -really- says is to make sure that (GETF X 'C 3)

will later return 3, which that value of X does. As such, I don't

even think the code should be ignored. I would prefer this

interpretation if we could get consensus, and would appreciate your

listing it as an option in your writeup, with me favoring it. Two

pieces of rationale you might add to the writeup are that (a) this

permits an application to be more space-conservative and (b) this

permits an application to not gratuitously modify pages of data that

don't really need to be modified, and hence may sometimes result in

smaller dumps or smaller working sets in some implementations that

either permit dumping an incremental image containing only the

modified pages, or that have an initial data set of copy-on-modify


As a fall-back, I think your clarification would be an improvement

over the status quo. But I think it's not as elegant.

Sandra Loosemore says:

I think we'd need to spec this out very carefully. Should this

behavior be required or simply permitted? Does an explicit default

of NIL do the same thing as no default? Does only SETF of GETF

behave this way, or should we generalize this to require/permit

*any* SETF place not to actually update the place unnecessarily?

In the general case, what predicate would be used to compare the

new value to the value that would be returned by the accessor?

While I agree this is an attractive idea on the surface, the more I

think about these questions, the more I become convinced that this

is an incompatible change and probably not a good idea overall.


[Starting Points][Contents][Index][Symbols][Glossary][Issues]
Copyright 1996-2005, LispWorks Ltd. All rights reserved.