[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

macro invocation within macrolet - howto?

Helmut Jarausch

4/8/2015 7:50:00 AM

Hi,

as an example I'd like to write a macro for accessing functions stored
in a struct. Then I'd like to use this macro within a macrolet.
This doesn't work (probably) because macrolet doesn't evaluate its
first argument.

Can this be done in Common Lisp?

I could write a macro which generates the whole macrolet invocation but that's
not the solution I'm looking for since I'd like to use several such macros in an
unspecified way within a macrolet.

Here is an example which does not work (yet)

(defstruct Node
(key-fct nil :type (function(Node) string))
(Name "" :type string)
)

(defun Node-Key(Nd)
(declare (Node Nd))
(format nil ">>>~a<<<" (ND-Name Nd)))


(defparameter MyNode (make-Node :Name "ItsMe" :key-fct #'Node-Key))


(defmacro struct-access (method method-fct)
`(,method(This) (let ((obj (gensym)))
`(let ((,obj ,This)) (funcall (,',method-fct ,obj) ,obj)))))


(macrolet (((struct-access get-key ND-key-fct)))
(get-key MyNode))

;; E R R O R
;; The list ((STRUCT-ACCESS GET-KEY ND-KEY-FCT)) is too short
;; to be a legal local macro definition.


Many thanks for a hint,
Helmut
14 Answers

Pascal J. Bourguignon

4/8/2015 9:23:00 AM

0

Carlos <angus@quovadis.com.ar> writes:

> On 08/04/2015 9:50, jarausch@skynet.be wrote:
>> Hi,
>>
>> as an example I'd like to write a macro for accessing functions stored
>> in a struct. Then I'd like to use this macro within a macrolet.
>> This doesn't work (probably) because macrolet doesn't evaluate its
>> first argument.
>>
>> Can this be done in Common Lisp?
>>
>> I could write a macro which generates the whole macrolet invocation but that's
>> not the solution I'm looking for since I'd like to use several such macros in an
>> unspecified way within a macrolet.
>>
>> Here is an example which does not work (yet)
>>
>> (defstruct Node
>> (key-fct nil :type (function(Node) string))
>> (Name "" :type string)
>> )
>>
>> (defun Node-Key(Nd)
>> (declare (Node Nd))
>> (format nil ">>>~a<<<" (ND-Name Nd)))
>>
>>
>> (defparameter MyNode (make-Node :Name "ItsMe" :key-fct #'Node-Key))
>>
>>
>> (defmacro struct-access (method method-fct)
>> `(,method(This) (let ((obj (gensym)))
>> `(let ((,obj ,This)) (funcall (,',method-fct ,obj) ,obj)))))
>>
>>
>> (macrolet (((struct-access get-key ND-key-fct)))
>> (get-key MyNode))
>>
>> ;; E R R O R
>> ;; The list ((STRUCT-ACCESS GET-KEY ND-KEY-FCT)) is too short
>> ;; to be a legal local macro definition.
>>
>>
>> Many thanks for a hint,
>> Helmut
>>
>
> All to avoid writing FUNCALL, no? ;)
>
> You can use classes, instead of structs (create a small class with
> just key-fct, and define the method get-key on it. Then, make it the
> parent of the others).
>
> Or you can define your own whole construct. For example,
>
> (defmacro with-struct-accesses (pairs &body body)
> `(flet ,(mapcar (lambda (pair)
> `(,(car pair) (this)
> (funcall (,(cadr pair) this) this)))
> pairs)
> ,@body))
>
> usage:
>
> (with-struct-accesses ((get-key nd-key-fct)
> (get-other-key other-key-fct))
> (get-key node))

Or just use with-accessors

(with-accessors ((key nd-key-fct)
(other-key other-key-fct)) node
(setf key other-key))


(with-accessors ((src-key nd-key-fct)) src-node
(with-accessors ((dst-key nd-key-fct)) dst-node
(setf dst-key src-key)))


--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Carlos

4/8/2015 9:24:00 AM

0

On 08/04/2015 9:50, jarausch@skynet.be wrote:
> Hi,
>
> as an example I'd like to write a macro for accessing functions stored
> in a struct. Then I'd like to use this macro within a macrolet.
> This doesn't work (probably) because macrolet doesn't evaluate its
> first argument.
>
> Can this be done in Common Lisp?
>
> I could write a macro which generates the whole macrolet invocation but that's
> not the solution I'm looking for since I'd like to use several such macros in an
> unspecified way within a macrolet.
>
> Here is an example which does not work (yet)
>
> (defstruct Node
> (key-fct nil :type (function(Node) string))
> (Name "" :type string)
> )
>
> (defun Node-Key(Nd)
> (declare (Node Nd))
> (format nil ">>>~a<<<" (ND-Name Nd)))
>
>
> (defparameter MyNode (make-Node :Name "ItsMe" :key-fct #'Node-Key))
>
>
> (defmacro struct-access (method method-fct)
> `(,method(This) (let ((obj (gensym)))
> `(let ((,obj ,This)) (funcall (,',method-fct ,obj) ,obj)))))
>
>
> (macrolet (((struct-access get-key ND-key-fct)))
> (get-key MyNode))
>
> ;; E R R O R
> ;; The list ((STRUCT-ACCESS GET-KEY ND-KEY-FCT)) is too short
> ;; to be a legal local macro definition.
>
>
> Many thanks for a hint,
> Helmut
>

All to avoid writing FUNCALL, no? ;)

You can use classes, instead of structs (create a small class with just
key-fct, and define the method get-key on it. Then, make it the parent
of the others).

Or you can define your own whole construct. For example,

(defmacro with-struct-accesses (pairs &body body)
`(flet ,(mapcar (lambda (pair)
`(,(car pair) (this)
(funcall (,(cadr pair) this) this)))
pairs)
,@body))

usage:

(with-struct-accesses ((get-key nd-key-fct)
(get-other-key other-key-fct))
(get-key node))

etc...
--

Kenneth Tilton

4/8/2015 9:25:00 AM

0

On Wednesday, April 8, 2015 at 3:50:34 AM UTC-4, jara...@skynet.be wrote:
> Hi,
>
> as an example I'd like to write a macro for accessing functions stored
> in a struct. Then I'd like to use this macro within a macrolet.
> This doesn't work (probably) because macrolet doesn't evaluate its
> first argument.
>
> Can this be done in Common Lisp?
>
> I could write a macro which generates the whole macrolet invocation but that's
> not the solution I'm looking for since I'd like to use several such macros in an
> unspecified way within a macrolet.

You have taken "writes code that writes code" a bridge too far and to a place you do not want to be anyway.

Lisp can do this to you.

Calm down. Back up at least one bridge.

One sign you have taken a severely wrong turn is that you are defining struct accessor wrappers in a macrolet. Anything so specific it goes in a macrolet does not need to be auto-written by a macro, it can just be coded in the damn macrolet.

And if these macros are not that specific, code them once, with the defstruct. If you need to get your macro-writing fix, write a defstruct wrapper macro that defs the struct and writes the struct accessor macros, too.

-hk

>
> Here is an example which does not work (yet)
>
> (defstruct Node
> (key-fct nil :type (function(Node) string))
> (Name "" :type string)
> )
>
> (defun Node-Key(Nd)
> (declare (Node Nd))
> (format nil ">>>~a<<<" (ND-Name Nd)))
>
>
> (defparameter MyNode (make-Node :Name "ItsMe" :key-fct #'Node-Key))
>
>
> (defmacro struct-access (method method-fct)
> `(,method(This) (let ((obj (gensym)))
> `(let ((,obj ,This)) (funcall (,',method-fct ,obj) ,obj)))))
>
>
> (macrolet (((struct-access get-key ND-key-fct)))
> (get-key MyNode))
>
> ;; E R R O R
> ;; The list ((STRUCT-ACCESS GET-KEY ND-KEY-FCT)) is too short
> ;; to be a legal local macro definition.
>
>
> Many thanks for a hint,
> Helmut

Carlos

4/8/2015 9:53:00 AM

0

On 08/04/2015 11:23, Pascal J. Bourguignon wrote:
> Carlos <angus@quovadis.com.ar> writes:
>
>> On 08/04/2015 9:50, jarausch@skynet.be wrote:
>>> Hi,
>>>
>>> as an example I'd like to write a macro for accessing functions stored
>>> in a struct. Then I'd like to use this macro within a macrolet.
>>> This doesn't work (probably) because macrolet doesn't evaluate its
>>> first argument.
>>>
>>> Can this be done in Common Lisp?
>>>
>>> I could write a macro which generates the whole macrolet invocation but that's
>>> not the solution I'm looking for since I'd like to use several such macros in an
>>> unspecified way within a macrolet.
>>>
>>> Here is an example which does not work (yet)
>>>
>>> (defstruct Node
>>> (key-fct nil :type (function(Node) string))
>>> (Name "" :type string)
>>> )
>>>
>>> (defun Node-Key(Nd)
>>> (declare (Node Nd))
>>> (format nil ">>>~a<<<" (ND-Name Nd)))
>>>
>>>
>>> (defparameter MyNode (make-Node :Name "ItsMe" :key-fct #'Node-Key))
>>>
>>>
>>> (defmacro struct-access (method method-fct)
>>> `(,method(This) (let ((obj (gensym)))
>>> `(let ((,obj ,This)) (funcall (,',method-fct ,obj) ,obj)))))
>>>
>>>
>>> (macrolet (((struct-access get-key ND-key-fct)))
>>> (get-key MyNode))
>>>
>>> ;; E R R O R
>>> ;; The list ((STRUCT-ACCESS GET-KEY ND-KEY-FCT)) is too short
>>> ;; to be a legal local macro definition.
>>>
>>>
>>> Many thanks for a hint,
>>> Helmut
>>>
>>
>> All to avoid writing FUNCALL, no? ;)
>>
>> You can use classes, instead of structs (create a small class with
>> just key-fct, and define the method get-key on it. Then, make it the
>> parent of the others).
>>
>> Or you can define your own whole construct. For example,
>>
>> (defmacro with-struct-accesses (pairs &body body)
>> `(flet ,(mapcar (lambda (pair)
>> `(,(car pair) (this)
>> (funcall (,(cadr pair) this) this)))
>> pairs)
>> ,@body))
>>
>> usage:
>>
>> (with-struct-accesses ((get-key nd-key-fct)
>> (get-other-key other-key-fct))
>> (get-key node))
>
> Or just use with-accessors
>
> (with-accessors ((key nd-key-fct)
> (other-key other-key-fct)) node
> (setf key other-key))
>
>
> (with-accessors ((src-key nd-key-fct)) src-node
> (with-accessors ((dst-key nd-key-fct)) dst-node
> (setf dst-key src-key)))

It's not enough; he wants to FUNCALL the value returned by the accessor.

--

Pascal J. Bourguignon

4/8/2015 9:57:00 AM

0

Carlos <angus@quovadis.com.ar> writes:

> It's not enough; he wants to FUNCALL the value returned by the accessor.

Oops, right.

Cf. com.informatimago.common-lisp.cesarum.a-star::with-functions

--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

smh

4/8/2015 10:59:00 AM

0

Also, with-accessors is not guaranteed to support structure classes, although it is allowed to do so and works on some implementations. Ditto for slot-value. Some members of the X3J13 CLOS subcommittee wanted to deprecate defstruct entirely.

Helmut Jarausch

4/8/2015 11:26:00 AM

0

On Wednesday, 8 April 2015 12:05:37 UTC+2, informatimago wrote:
> Cf. com.informatimago.common-lisp.cesarum.a-star::with-functions

Hi Pascal,
could you please give me an URL for this?

Many thanks,
Helmut

Helmut Jarausch

4/8/2015 11:34:00 AM

0

Many thanks, Carlos.
This is a nice solution without macrolet.

Helmut

Helmut Jarausch

4/8/2015 11:41:00 AM

0

On Wednesday, 8 April 2015 11:25:06 UTC+2, His Kennyness wrote:
> You have taken "writes code that writes code" a bridge too far and to a place you do not want to be anyway.
>
> Lisp can do this to you.
>
> Calm down. Back up at least one bridge.
>
> One sign you have taken a severely wrong turn is that you are defining struct accessor wrappers in a macrolet. Anything so specific it goes in a macrolet does not need to be auto-written by a macro, it can just be coded in the damn macrolet.

Coding it directly within macrolet is just tedious when it has to done many times.
I remember the saying "most programming errors are caused by cut'n paste"

> And if these macros are not that specific, code them once, with the defstruct. If you need to get your macro-writing fix, write a defstruct wrapper macro that defs the struct and writes the struct accessor macros, too.

Could you please elaborate on this. I didn't understand what you are saying.
Thanks,
Helmut

Madhu

4/8/2015 11:48:00 AM

0


* smh <2b902333-7d42-48e8-bcdd-a99ffb3141ef@googlegroups.com> :
Wrote on Wed, 8 Apr 2015 03:59:14 -0700 (PDT):

| Also, with-accessors is not guaranteed to support structure classes,
| although it is allowed to do so and works on some implementations.
| Ditto for slot-value.

Are you sure? SLOT-VALUE is not guaranteed to work on structure classes
or conditions, and this restriction would carry over to WITH-SLOTS.
There is no reason for this restriction to carry over to WITH-ACCESSORS
because the accessors are directly specified in this form.

The spec states that

(with-accessors (slot-entry1 ... slot-entryn) instance-form form1 ... formk)

expands into the equivalent of

(let ((in instance-form))
(symbol-macrolet (Q1 ... Qn) form1 ... formk))

where Qi is

(variable-namei () (accessor-namei in))

** if slot-entryi is of the form (variable-namei 'slot-namei))

This is conforming common lisp for structs.

| Some members of the X3J13 CLOS subcommittee wanted to deprecate
| defstruct entirely.

We all know now how shortsighted they were.

---Madhu

PS ** this line is omitted in the spec