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


Issue SETF-MULTIPLE-STORE-VARIABLES Writeup

Issue:         SETF-MULTIPLE-STORE-VARIABLES

References: CLtL, pp.93-107

Lisp Pointers, v2n2, pp.27-41

Category: ADDITION

Edit history: Version 1, 5-Dec-88, Pavel

Version 2, 22-Mar-89, Moon, simplify, update from discussion

Problem description:

The description of GET-SETF-METHOD-MULTIPLE-VALUE on page 107 of CLtL

states that there are no cases in Common Lisp that allow multiple values

to be stored into a generalized variable. This is seen by some as an

arbitrary decision in light of the fact that a very reasonable semantics

exists for multiple values being assigned by several Common Lisp macros,

including SETF. The rationale on page 103 of CLtL suggests that this

decision might be changed in the future.

Proposal (SETF-MULTIPLE-STORE-VARIABLES:ALLOW):

Extend the semantics of the macros SETF, PSETF, SHIFTF, ROTATEF, and

ASSERT to allow "places" whose SETF methods have more than one "store

variable". In such cases, the macros accept as many values from the

newvalue form as there are store variables. As usual, extra values

are ignored and missing values default to NIL.

Extend the long form of DEFSETF to allow the specification of more

than one "store variable", with the obvious semantics.

Clarify that GET-SETF-METHOD signals an error if there would be more

than one store-variable.

Test Cases/Examples:

(defstruct region width height)

(defun region-size (region)

(values

(region-width region)

(region-height region)))

(defsetf region-size (region) (width height)

`(values

(setf (region-width ,region) ,width)

(setf (region-height ,region) ,height)))

(setf my-reg (make-region :width 10 :height 20))

=> #S(REGION :WIDTH 10 :HEIGHT 20)

(region-size my-reg)

=> 10

20

(setf (region-size my-reg) (values 30 40))

=> 30

40

(region-size my-reg)

=> 30

40

Rationale:

This change removes an artificial restriction on the semantics of

several Common Lisp macros, allowing a broader set of contexts in

which generalized variables can be used. For example, it is not

difficult to write a reasonable SETF method for the VALUES function,

yielding a powerful MULTIPLE-VALUE-SETF form:

(setf (values (car a) (gethash b 'c) (aref d 13))

(some-hairy-computation))

In the language as currently defined, this example would have to be

written:

(multiple-value-bind (x y z)

(some-hairy-computation)

(setf (car a) x

(gethash b 'c) y

(aref d 13) z))

Many other (perhaps more compelling) examples of generalized variables

holding more than one value can easily be imagined. Their use,

however, is severely discouraged by Common Lisp as defined in CLtL,

since none of the built-in macros will accept them.

The clarification of GET-SETF-METHOD makes explicit what is implied

by CLtL (CLtL uses the word "guarantee", whose relationship to

signalling of errors is unclear).

Current practice:

I do not know of any implementations that allow all of this extension.

Xerox Lisp does not signal an error, but this is probably due to a bug

in GET-SETF-METHOD. Lucid signals an error in GET-SETF-METHOD.

Symbolics Genera supports the proposal in SETF and PSETF, but not in

SHIFTF, ROTATEF, and ASSERT.

Cost to Implementors:

A relatively minor fix to each of the affected macros suffices. For

example, to fix SETF itself, one need only call

GET-SETF-METHOD-MULTIPLE-VALUE instead of GET-SETF-METHOD and emit a

MULTIPLE-VALUE-BIND instead of a LET for binding the store variables.

Cost to Users:

This is an upward-compatible change; no user code must change.

Cost of non-adoption:

Yet another non-uniformity in the language, yet another piece of

mechanism without a clear use (GET-SETF-METHOD-MULTIPLE-VALUE).

Benefits:

Wider applicability of a reasonably nice abstraction, the removal of

an artificial prohibition.

Aesthetics:

People may disagree about whether this is a simplification or not. I

am firmly on the side that believes that such removal of

non-uniformities is a simplifying force in the language.

Discussion:

Pavel supports this proposal.

Moon supports this proposal except he is not sure about the

inclusion of ASSERT.

GSB suggests that this is a clarification rather than an addition,

because the lack of any predefined setf-methods that use multiple

store variables should not mean that SETF, etc. should not work with

such a setf-method if the user defined one. The problem is that CLtL

examples such as the ones for SHIFTF on p.98 and the simplified

definition for SETF on p.107 contradict this proposal, and might have

been taken as specifications, rather than simplified examples, by

some readers.

Predefined SETF methods for such functions as VALUES, CONS, and VECTOR

could have been proposed, but we refrained. This proposal is necessary

to allow the user to write such methods for himself, but if this

proposal is adopted those setf-methods are very easy to write in

a portable fashion.


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