Re: Auto-creation in a SETF method

Peter Seibel <[email protected]> 23 Feb 2004 12:25:34 -0800
Newsgroups gmane.lisp.clump
Message-ID <[email protected]>
JP Massar <[email protected]> writes:

> Suppose I've defined an class called ZOOP, and it has a slot SLOT.
> 
> 
> Now suppose, for whatever perverted reason, I want the following:
> 
> (let ((x nil))
>    (setf (ZOOP-SLOT x) 23))
> 
> to 'just work', that is, if X is not a ZOOP, I want to effectively have the
> SETF generate
> 
> (SETQ X (MAKE-INSTANCE :ZOOP))
> 
> and then do the 'real' SETF using a setf function or whatever.
> 
> So
> 
> (progn
>    (when (not (typep x 'zoop)) (setq x (make-instance :zoop)))
>    (setf-zoop-slot x 23))
> 
> (For simplicity, for the moment, let's say I only want it to work when
> X is a symbol, not an arbitrary place.  And let's ignore completely what
> might or might not be the semantics when X is not a place)
>
> After some perusal of DEFINE-SETF-EXPANDER, DEFSETF and whatnot,
> I am convincing myself that this is simply not possible.

Unless I misunderstand your requirements here is--I think--an
existance proof that it *is* possible. This also handles X being an
arbitrary place and gives a semi-meaningful error message if X is not
a place:

  (defclass zoop () ((slot :initarg :slot :reader zoop-slot)))

  (define-setf-expander zoop-slot (x &environment env)
    (multiple-value-bind (xtemps xvals xstore-vars xwriter xreader)
        (get-setf-expansion x env)
      (let ((store (gensym))
            (xstore (first xstore-vars)))
        (if (rest xstore-vars) (error "To many store vars."))
        (values
         nil
         nil
         (list store)
         `(let*
              (,@(mapcar #'list xtemps xvals)
                 (,xstore 
                  (if (typep ,xreader 'zoop) ,xreader (make-instance 'zoop))))
            (setf (slot-value ,xstore 'slot) ,store)
            ,xwriter
            ,store)
         `(slot-value ,xreader 'slot)))))


-Peter

-- 
Peter Seibel                                      [email protected]

         Lisp is the red pill. -- John Fraser, comp.lang.lisp