From: dave
Subject: define-modify-macro
Date: 
Message-ID: <1d6f97f5.0310240838.71352bb@posting.google.com>
Hi,

I am relatively new to lisp (weeks not months) but have hacked
together a nice little code generator with some structures in it.
e.g.
(defstruct j-class
  name
  vo
  dbTable
  primaryKey
  queryCantRead)

Now I have a string (read parsed from a file) of "name" and I want to
write a macro which given a symbol a set to "name" and a symbol b set
to "bob" and an object obj of type j-class will do (setf (j-class-name
obj) b) which I cannot believe is hard.

Obviously I have been trying to do this using macros (using clisp on
windows?) for many hours...

My attempt at a rubbish solution (that doesn't even pass "name" as an
argument yet) so far is:
(defun getname (a) (funcall (read-from-string "j-class-name") a))
(define-modify-macro gn (&rest args) getname)
(setf a (make-j-class))
(gn a "bob")

obviously not working (although not really obvious to me why).

Please can someone either:
1.  Explain define-modify-macro in english that a poor C programmer
might understand (not the explanation on the net which is trivial and
adds nothing to my zero understanding of it) or
2.  Give me the code that I may pour over it for more hours to try to
understand it.

Help!

Thanks,

David.


p.s. Even though very frustrated by this, lisp is v.v. cool.  First
language I've come across that seems a level up from normal.

From: Barry Margolin
Subject: Re: define-modify-macro
Date: 
Message-ID: <Btdmb.222$lK3.78@news.level3.com>
In article <···························@posting.google.com>,
dave <······@manfinancial.com> wrote:
>Hi,
>
>I am relatively new to lisp (weeks not months) but have hacked
>together a nice little code generator with some structures in it.
>e.g.
>(defstruct j-class
>  name
>  vo
>  dbTable
>  primaryKey
>  queryCantRead)
>
>Now I have a string (read parsed from a file) of "name" and I want to
>write a macro which given a symbol a set to "name" and a symbol b set
>to "bob" and an object obj of type j-class will do (setf (j-class-name
>obj) b) which I cannot believe is hard.

You're not expressing it clearly, but I think what you're trying to do is
read a slot name from the file, and use this to access the corresponding
slot of an object.  There's a section of the Lisp FAQ devoted to this
problem.

One of the easiest solutions is to switch from DEFSTRUCT to DEFCLASS, since
CLOS offers the SLOT-VALUE function, which does precisely this.

>Obviously I have been trying to do this using macros (using clisp on
>windows?) for many hours...
>
>My attempt at a rubbish solution (that doesn't even pass "name" as an
>argument yet) so far is:
>(defun getname (a) (funcall (read-from-string "j-class-name") a))
>(define-modify-macro gn (&rest args) getname)
>(setf a (make-j-class))
>(gn a "bob")
>
>obviously not working (although not really obvious to me why).
>
>Please can someone either:
>1.  Explain define-modify-macro in english that a poor C programmer
>might understand (not the explanation on the net which is trivial and
>adds nothing to my zero understanding of it) or

DEFINE-MODIFY-MACRO is used for creating a macro that acts like INCF or
PUSH: it reads an old value out of a location, passes this and the other
arguments to a function, and stores the result back in the location.

To relate it to C, it's a way of defining new <op>= operators (INCF is
analogous to C's ++ and += operators).

>2.  Give me the code that I may pour over it for more hours to try to
>understand it.

DEFSTRUCT doesn't really provide a built-in way to do what you're trying to
do.  See the FAQ for some workarounds.

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Kenny Tilton
Subject: Re: define-modify-macro
Date: 
Message-ID: <bIdmb.37303$pT1.35600@twister.nyc.rr.com>
Barry Margolin wrote:
> In article <···························@posting.google.com>,
> dave <······@manfinancial.com> wrote:
> 
>>Hi,
>>
>>I am relatively new to lisp (weeks not months) but have hacked
>>together a nice little code generator with some structures in it.
>>e.g.
>>(defstruct j-class
>> name
>> vo
>> dbTable
>> primaryKey
>> queryCantRead)
>>
>>Now I have a string (read parsed from a file) of "name" and I want to
>>write a macro which given a symbol a set to "name" and a symbol b set
>>to "bob" and an object obj of type j-class will do (setf (j-class-name
>>obj) b) which I cannot believe is hard.
> 
> 
> You're not expressing it clearly, but I think what you're trying to do is
> read a slot name from the file, and use this to access the corresponding
> slot of an object.  There's a section of the Lisp FAQ devoted to this
> problem.
> 
> One of the easiest solutions is to switch from DEFSTRUCT to DEFCLASS, since
> CLOS offers the SLOT-VALUE function, which does precisely this.
> 
> 
>>Obviously I have been trying to do this using macros (using clisp on
>>windows?) for many hours...
>>
>>My attempt at a rubbish solution (that doesn't even pass "name" as an
>>argument yet) so far is:
>>(defun getname (a) (funcall (read-from-string "j-class-name") a))
>>(define-modify-macro gn (&rest args) getname)
>>(setf a (make-j-class))
>>(gn a "bob")
>>
>>obviously not working (although not really obvious to me why).
>>
>>Please can someone either:
>>1.  Explain define-modify-macro in english that a poor C programmer
>>might understand (not the explanation on the net which is trivial and
>>adds nothing to my zero understanding of it) or
> 
> 
> DEFINE-MODIFY-MACRO is used for creating a macro that acts like INCF or
> PUSH: it reads an old value out of a location, passes this and the other
> arguments to a function, and stores the result back in the location.
> 
> To relate it to C, it's a way of defining new <op>= operators (INCF is
> analogous to C's ++ and += operators).
> 
> 
>>2.  Give me the code that I may pour over it for more hours to try to
>>understand it.
> 
> 
> DEFSTRUCT doesn't really provide a built-in way to do what you're trying to
> do.  See the FAQ for some workarounds.
> 

Well, this:

    (read-from-string (format nil "j-class-~a" (string-downcase "NAME")))

returns the symbol 'j-class-name, which can then be used to /read/ a 
structure:

   (funcall 'j-class-name obj) ;; substitute above form for 'j-class-name

I have never been real strong on setters. Is there some way to likewise 
refer to (setf j-class-name) to use funcall to set the value? I had no 
luck with a couple of attempts, but like I said, this is still a dark 
area for me.

kenny


-- 
http://tilton-technology.com
What?! You are a newbie and you haven't answered my:
  http://alu.cliki.net/The%20Road%20to%20Lisp%20Survey
From: Barry Margolin
Subject: Re: define-modify-macro
Date: 
Message-ID: <QRdmb.224$lK3.3@news.level3.com>
In article <·····················@twister.nyc.rr.com>,
Kenny Tilton  <·······@nyc.rr.com> wrote:
>Well, this:
>
>    (read-from-string (format nil "j-class-~a" (string-downcase "NAME")))
>
>returns the symbol 'j-class-name, which can then be used to /read/ a 
>structure:
>
>   (funcall 'j-class-name obj) ;; substitute above form for 'j-class-name
>
>I have never been real strong on setters. Is there some way to likewise 
>refer to (setf j-class-name) to use funcall to set the value? I had no 
>luck with a couple of attempts, but like I said, this is still a dark 
>area for me.

No, there's nothing built in that serves the analogous purpose for
DEFSTRUCT setters.  That's why I said this is hard to do.  Here's the
simplest I can come up with:

(defun set-j-class-slot (slot-name obj value)
  (eval `(setf (,(read-from-string slot-name) ',obj) ',value)))

I consider this a really gross hack.  The FAQ shows some more complicated,
but (IMHO) elegant, ways to do it.

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Barry Margolin
Subject: Re: define-modify-macro
Date: 
Message-ID: <m7emb.225$lK3.55@news.level3.com>
In article <···············@news.level3.com>,
Barry Margolin  <··············@level3.com> wrote:
>(defun set-j-class-slot (slot-name obj value)
>  (eval `(setf (,(read-from-string slot-name) ',obj) ',value)))

Oops, that's not quite right, I forgot to prepend "j-class-" to the slot
name.  It should be:

(defun set-j-class-slot (slot-name obj value)
  (eval `(setf (,(read-from-string (format nil "j-class-%a" slot-name))
                ',obj)
               ',value)))

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Frode Vatvedt Fjeld
Subject: Re: define-modify-macro
Date: 
Message-ID: <2h1xt2imng.fsf@vserver.cs.uit.no>
······@manfinancial.com (dave) writes:

> [..] Now I have a string (read parsed from a file) of "name" and I
> want to write a macro which given a symbol a set to "name" and a
> symbol b set to "bob" and an object obj of type j-class will do
> (setf (j-class-name obj) b) which I cannot believe is hard.

I couldn't understand what it was you wanted to do. Could you specify
the macro you want by its parameters, return-value, side-effects,
and an example use? And why does it have to be a macro, not a function?

-- 
Frode Vatvedt Fjeld
From: Kalle Olavi Niemitalo
Subject: Re: define-modify-macro
Date: 
Message-ID: <87y8va2ue6.fsf@Astalo.kon.iki.fi>
······@manfinancial.com (dave) writes, although not in this order:

> (define-modify-macro gn (&rest args) getname)
> (gn a "bob")

The second form will expand to something equivalent to:

  (setf a (getname a "bob"))

whereas your intention was more like:

  (setf (getname a) "bob")

It seems to me that DEFINE-MODIFY-MACRO is just not the right
tool here.  It defines macros that are similar to INCF: they take
a place as the first argument, read the value of that place and
write a new value to the same place.  In your use, the first
parameter of the macro is A, but the value should be stored in
the NAME slot of the object, rather than directly to A itself.

> Now I have a string (read parsed from a file) of "name" and I want to
> write a macro which given a symbol a set to "name" and a symbol b set
> to "bob" and an object obj of type j-class will do (setf (j-class-name
> obj) b) which I cannot believe is hard.

I think the easiest way would be to convert the DEFSTRUCT form to
DEFCLASS.

  (defclass j-class ()
    ((name          :accessor j-class-name          :initarg :name)
     (vo            :accessor j-class-vo            :initarg :vo)
     (dbTable       :accessor j-class-dbTable       :initarg :dbTable)
     (primaryKey    :accessor j-class-primaryKey    :initarg :primaryKey)
     (queryCantRead :accessor j-class-queryCantRead :initarg :queryCantRead)))

Then, you can do things like:

  (let ((a 'name)
        (b 'bob)
        (obj (make-instance 'j-class)))
    (setf (slot-value obj a) b))

This might work with DEFSTRUCT too, but the standard does not
guarantee that.  (In the description of SLOT-VALUE: "Note in
particular that the behavior for conditions and structures is
not specified.")