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
passing setf-able place to a function?
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  16 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Trastabuga  
View profile  
 More options Apr 30 2010, 12:08 pm
Newsgroups: comp.lang.lisp
From: Trastabuga <lisper...@gmail.com>
Date: Fri, 30 Apr 2010 09:08:32 -0700 (PDT)
Local: Fri, Apr 30 2010 12:08 pm
Subject: passing setf-able place to a function?
Hi

I have a simple task:
Given a class, I need a function that can add elements to one of the
fields of the class.
It's easy to do if the function knows the name of the field, but what
if the function doesn't know it and we need to pass it as an input
parameter to the function.
Let's say
(defclass test1 ()
  ((fld1 :accessor test1-fld1 :initarg :fld1 :type list)))

(setq o (make-instance 'test1 :fld1 nil))
(defun append-element (o el)
  (with-slots (fld1) o
    (setf fld1 (append fld1 (list el)))))

How to modify the append-element function so that it doesn't know
about the fld1 and had semantics of (append-element o el field-name)
so we can call it like (append-element o 'a 'fld1)?


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Trastabuga  
View profile  
 More options Apr 30 2010, 12:36 pm
Newsgroups: comp.lang.lisp
From: Trastabuga <lisper...@gmail.com>
Date: Fri, 30 Apr 2010 09:36:59 -0700 (PDT)
Local: Fri, Apr 30 2010 12:36 pm
Subject: Re: passing setf-able place to a function?
On Apr 30, 12:08 pm, Trastabuga <lisper...@gmail.com> wrote:

I am sure, it can be done as a macro
(defmacro append-element (o el field)
  `(with-slots (,field) o
    (setf ,field (append ,field (list ,el)))))

But I'd like to know if it's possible to pass some kind of setf-able
place to the function?


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Frode V. Fjeld  
View profile  
 More options Apr 30 2010, 12:39 pm
Newsgroups: comp.lang.lisp
From: "Frode V. Fjeld" <fr...@netfonds.no>
Date: Fri, 30 Apr 2010 18:39:31 +0200
Local: Fri, Apr 30 2010 12:39 pm
Subject: Re: passing setf-able place to a function?

Trastabuga <lisper...@gmail.com> writes:
> (defclass test1 ()
>   ((fld1 :accessor test1-fld1 :initarg :fld1 :type list)))

> (setq o (make-instance 'test1 :fld1 nil))
> (defun append-element (o el)
>   (with-slots (fld1) o
>     (setf fld1 (append fld1 (list el)))))

> How to modify the append-element function so that it doesn't know
> about the fld1 and had semantics of (append-element o el field-name)
> so we can call it like (append-element o 'a 'fld1)?

Not entirely sure I understand, but maybe the SLOT-VALUE accessor is
what you're looking for?

(defun append-element (object element slot)
  (setf (slot-value object slot)
        (append (slot-value object slot)
                (list element))))

--
Frode V. Fjeld


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Peter Keller  
View profile  
 More options Apr 30 2010, 12:45 pm
Newsgroups: comp.lang.lisp
From: Peter Keller <psil...@merlin.cs.wisc.edu>
Date: 30 Apr 2010 16:45:03 GMT
Local: Fri, Apr 30 2010 12:45 pm
Subject: Re: passing setf-able place to a function?

Trastabuga <lisper...@gmail.com> wrote:
> On Apr 30, 12:08?pm, Trastabuga <lisper...@gmail.com> wrote:

> I am sure, it can be done as a macro
> (defmacro append-element (o el field)
>  `(with-slots (,field) o
>    (setf ,field (append ,field (list ,el)))))

Whenever I see this form in a macro:

(setf ,x (stuff ,x))

I think it is wrong due to multiple evaluation (from "On Lisp").

However, lots of people keep reiterating it in posts here.

Are there well-known situations where it isn't wrong?

-pete


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Trastabuga  
View profile  
 More options Apr 30 2010, 12:58 pm
Newsgroups: comp.lang.lisp
From: Trastabuga <lisper...@gmail.com>
Date: Fri, 30 Apr 2010 09:58:04 -0700 (PDT)
Local: Fri, Apr 30 2010 12:58 pm
Subject: Re: passing setf-able place to a function?
On Apr 30, 12:39 pm, "Frode V. Fjeld" <fr...@netfonds.no> wrote:

Yes, that will do! Thank you Frode!

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options Apr 30 2010, 1:08 pm
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@tfeb.org>
Date: Fri, 30 Apr 2010 18:08:04 +0100
Local: Fri, Apr 30 2010 1:08 pm
Subject: Re: passing setf-able place to a function?
On 2010-04-30 17:08:32 +0100, Trastabuga said:

> How to modify the append-element function so that it doesn't know
> about the fld1 and had semantics of (append-element o el field-name)
> so we can call it like (append-element o 'a 'fld1)?

You can use SLOT-VALUE if you are happy to set the slot directly.  If
you want to use the accessor (which you probably should want to do)
then I think that you can use FDEFINITION, based on the accessor's name:

(defun set-field (o accessor new)
  (funcall (fdefinition `(setf ,accessor)) new o))

--tim


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Trastabuga  
View profile  
 More options Apr 30 2010, 1:41 pm
Newsgroups: comp.lang.lisp
From: Trastabuga <lisper...@gmail.com>
Date: Fri, 30 Apr 2010 10:41:29 -0700 (PDT)
Local: Fri, Apr 30 2010 1:41 pm
Subject: Re: passing setf-able place to a function?
On Apr 30, 1:08 pm, Tim Bradshaw <t...@tfeb.org> wrote:

> On 2010-04-30 17:08:32 +0100, Trastabuga said:

> > How to modify the append-element function so that it doesn't know
> > about the fld1 and had semantics of (append-element o el field-name)
> > so we can call it like (append-element o 'a 'fld1)?

> You can use SLOT-VALUE if you are happy to set the slot directly.  If
> you want to use the accessor (which you probably should want to do)
> then I think that you can use FDEFINITION, based on the accessor's name:

> (defun set-field (o accessor new)
>   (funcall (fdefinition `(setf ,accessor)) new o))

> --tim

Thank you, Tim, very good example.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Norbert_Paul  
View profile  
 More options May 2 2010, 9:19 am
Newsgroups: comp.lang.lisp
From: Norbert_Paul <norbertpauls_spam...@yahoo.com>
Date: Sun, 02 May 2010 15:19:06 +0200
Local: Sun, May 2 2010 9:19 am
Subject: Re: passing setf-able place to a function?
You might try #'(setf foo) to get the writer part of the accessor #'foo.
I tried it, but I don't know if this is always possible.

(defun append-element (o el getter setter)
    (funcall setter (append (funcall getter o) (list el)) o)
)

(append-element o :new-el #'test1-fld1 #'(setf test1-fld1))

Norbert


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options May 2 2010, 10:54 am
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@tfeb.org>
Date: Sun, 2 May 2010 15:54:41 +0100
Local: Sun, May 2 2010 10:54 am
Subject: Re: passing setf-able place to a function?
On 2010-05-02 14:19:06 +0100, Norbert_Paul said:

> You might try #'(setf foo) to get the writer part of the accessor #'foo.
> I tried it, but I don't know if this is always possible.

This works, but it only works if you know the name FOO: you can't say
(let ((fun 'foo) #'(setf fun)) for instance: you need FDEFINITION for
that.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Norbert_Paul  
View profile  
 More options May 2 2010, 11:13 am
Newsgroups: comp.lang.lisp
From: Norbert_Paul <norbertpauls_spam...@yahoo.com>
Date: Sun, 02 May 2010 17:13:51 +0200
Local: Sun, May 2 2010 11:13 am
Subject: Re: passing setf-able place to a function?

Tim Bradshaw wrote:
> On 2010-05-02 14:19:06 +0100, Norbert_Paul said:
> This works, but it only works if you know the name FOO: you can't say
> (let ((fun 'foo) #'(setf fun)) for instance: you need FDEFINITION for that.

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)))

?


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options May 2 2010, 2:36 pm
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@tfeb.org>
Date: Sun, 2 May 2010 19:36:32 +0100
Local: Sun, May 2 2010 2:36 pm
Subject: Re: passing setf-able place to a function?
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

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Norbert_Paul  
View profile  
 More options May 3 2010, 9:02 am
Newsgroups: comp.lang.lisp
From: Norbert_Paul <norbertpauls_spam...@yahoo.com>
Date: Mon, 03 May 2010 15:02:56 +0200
Local: Mon, May 3 2010 9:02 am
Subject: Re: passing setf-able place to a function?
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.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pillsy  
View profile  
 More options May 3 2010, 10:51 am
Newsgroups: comp.lang.lisp
From: Pillsy <pillsb...@gmail.com>
Date: Mon, 3 May 2010 07:51:27 -0700 (PDT)
Local: Mon, May 3 2010 10:51 am
Subject: Re: passing setf-able place to a function?
On Apr 30, 12:08 pm, Trastabuga <lisper...@gmail.com> wrote:

> Given a class, I need a function that can add elements to one of the
> fields of the class.
> It's easy to do if the function knows the name of the field, but what
> if the function doesn't know it and we need to pass it as an input
> parameter to the function.
> Let's say
> (defclass test1 ()
>   ((fld1 :accessor test1-fld1 :initarg :fld1 :type list)))
> (setq o (make-instance 'test1 :fld1 nil))
> (defun append-element (o el)
>   (with-slots (fld1) o
>     (setf fld1 (append fld1 (list el)))))

If I wanted to stick with a function-based (as opposed to macro-based)
solution, I would do it like this:

(defun append-element (object element getter setter)
  (let ((current (funcall getter object)))
     (funcall setter (append fldl (list element)) object)))

This will be pretty easy to use with your class as written. You use

(append-element o 'foo #'test-fld1 #'(setf test-fld1))

It's also a fairly general solution. Consider:

(defparameter *table* (make-hash-table))

(append-element *table* 'baz
                (lambda (ht) (gethash 'bar ht))
                (lambda (val ht) (setf (gethash 'bar ht) val))

You can build more convenient functions on top of this one, like

(append-element-to-slot (object element slot)
  (append-element object element
                         (lambda (o) (slot-value o slot))
                         (lambda (v o) (setf (slot-value o slot))))

(append-element-to-table-value (table element key)
  (append-element table element
                        (lambda (ht) (gethash key ht))
                        (lambda (v ht) (setf (gethash key ht) v)))

I doubt it will ever be as syntactically clean as a macro-based
solution, but it's hard to beat its ease of implementation.

Cheers,
Pillsy


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal J. Bourguignon  
View profile  
 More options May 3 2010, 11:03 am
Newsgroups: comp.lang.lisp
From: p...@informatimago.com (Pascal J. Bourguignon)
Date: Mon, 03 May 2010 17:03:36 +0200
Local: Mon, May 3 2010 11:03 am
Subject: Re: passing setf-able place to a function?

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tamas K Papp  
View profile  
 More options May 3 2010, 11:33 am
Newsgroups: comp.lang.lisp
From: Tamas K Papp <tkp...@gmail.com>
Date: 3 May 2010 15:33:15 GMT
Local: Mon, May 3 2010 11:33 am
Subject: Re: passing setf-able place to a function?

This is really neat, thanks.

Tamas


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options May 3 2010, 1:31 pm
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@tfeb.org>
Date: Mon, 3 May 2010 18:31:31 +0100
Local: Mon, May 3 2010 1:31 pm
Subject: Re: passing setf-able place to a function?
On 2010-05-03 14:02:56 +0100, Norbert_Paul said:

> 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.

It pretty much has to work for ordinary CLOS classes (by "ordinary" I
mean "assuming no one has done too much MOP stuff"): If I can define a
method on (SETF FOO) then I can use FDEFINITION on it.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »