Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion passing setf-able place to a function?

Path: g2news2.google.com!news3.google.com!feeder.news-service.com!border1.nntp.ams.giganews.com!nntp.giganews.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail
From: p...@informatimago.com (Pascal J. Bourguignon)
Newsgroups: comp.lang.lisp
Subject: Re: passing setf-able place to a function?
Date: Mon, 03 May 2010 17:03:36 +0200
Organization: Informatimago
Lines: 99
Message-ID: <lz8w81auyf.fsf@informatimago.com>
References: <5adb5b25-b026-4f00-a885-6f0910775dd7@u30g2000prd.googlegroups.com> <hrjtvh$kp2$1@news.eternal-september.org> <hrk3nh$3vj$1@news.eternal-september.org> <hrk4mh$3v2$1@news.eternal-september.org> <hrkgng$9qd$1@news.eternal-september.org> <hrmhd0$ch5$1@news.eternal-september.org>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
X-Trace: individual.net I4huLT7DBFGhQZO6QFmRDwHSi1enz3YG1bZ8Fy9uyFJTv+5KzB
Cancel-Lock: sha1:N2E5NmRhMGFkNjBmYjZlMDJkM2Q1M2M0ODZiZjA2NTg4NTU1ZGM3YQ== sha1:HifA0FMQ8GUphepOGaUJ0FWCSPo=
Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA
      oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9
      033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac
      l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR
      mV+hO/VvFAAAAABJRU5ErkJggg==
X-Accept-Language:         fr, es, en
X-Disabled: X-No-Archive: no
User-Agent: Gnus/5.101 (Gnus v5.10.10) Emacs/23.1 (darwin)

Norbert_Paul <norbertpauls_spam...@yahoo.com> writes:

> Tim Bradshaw wrote:
>> On 2010-05-02 16:13:51 +0100, Norbert_Paul said:
>>> Did you mean
>>>
>>> (defun append-element (o el accessor)
>>> (let ((getter (fdefinition accessor))
>>> (setter (fdefinition `(setf ,accessor))))
>>> (funcall setter (append (funcall getter o) (list el)) o)))
>>
>> something like that
>>
> Does that always work?
>
> I searched the HS a lot but couldn'd find any guarantee that
> an accessor foo always has an (fdefinition `(setf ,foo)),
> neither could I find the contrary.

Indeed not.  It's not because you can write (setf (foo x) v) that you
can recover a (function (setf foo)) or a (fdefinition '(setf foo)).

SETF can implement the "standard" place in its own way, without having
a (setf foo) function defined.

The correct way to "reify" a random place in general, is to wrap it in
a closure, or a pair of closures.

See for example:
http://groups.google.com/group/comp.lang.lisp/msg/1799d5db9267c523
which is wrong, since it doesn't use get-setf-expansion to avoid
duplicate evaluation of the arguments to the place, but gives you the
closure side (it answered on a question on variables, not places).


So a full solution would be:

;;; Locatives with multiple-value places.

(defmacro & (place &environment env)
   (multiple-value-bind (vars vals store-vars writer-form reader-form) 
                            (get-setf-expansion place env)
       `(let* (,@(mapcar (function list) vars vals)
               ,@store-vars)
             (lambda (m &rest values)
                (ecase m 
                  ((set)
                      (psetf ,@(loop :for v :in store-vars :nconc (list v '(pop values))))
                      ,writer-form)
                   ((get)
                      ,reader-form))))))


(defun deref (locative) (funcall locative 'get))

;; Notice that using (defun (setf deref) ...) would prevent to store
;; multiple values, if the place accepted them.  So we must use
;; defsetf with a macro setter.

(defmacro set-deref (locative value-expression)
  `(multiple-value-call ,locative 'set ,value-expression))

(defsetf deref set-deref)


;; So that:

(let* ((a 1) (b 2) (c 3) (l (& (values a b c))))
       (print (multiple-value-list (deref l)))
       (setf (deref l) (values 4 5 6))
       (list a b c))

prints:  (1 2 3) 
returns: (4 5 6)

;; and

(let* ((a 1)
             (b 2)
             (c 3)
             (ls (vector (& (values a b c))
                         (& a)
                         (& b)
                         (& c)))
             (i -1))
       (print (multiple-value-list (deref (aref ls (incf i)))))
       (print (multiple-value-list (deref (aref ls (incf i)))))
       (decf i)
       (incf (deref (aref ls (incf i))) 10)
       (list (list i) a b c))

prints:  (1 2 3) 
         (1) 
returns: ((1) 11 2 3)


-- 
__Pascal Bourguignon__
http://www.informatimago.com