From: Vladimir Zolotykh
Subject: DEFCLASS question
Date: 
Message-ID: <3CFF8516.289A1CD@eurocom.od.ua>
Let me consider DEFCLASS macro. For my question it is essential that
it arranges its arguments in a list of lists and passes it to
:direct-slot argument of a ENSURE-CLASS. For example

  :my-func #'foo

becomes
  :direct-slots
  (list 
    (list .... ':my-func '#'foo .....)
    )

Of course when I try to get type of :my-func slot I see CONS instead of
function. Is it possible to have function there ? E.g.  prevent
quoting or something else solution ? Could you advise something.

-- 
Vladimir Zolotykh

From: Barry Margolin
Subject: Re: DEFCLASS question
Date: 
Message-ID: <DsNL8.12$qx5.40@paloalto-snr1.gtei.net>
In article <················@eurocom.od.ua>,
Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
>Let me consider DEFCLASS macro. For my question it is essential that
>it arranges its arguments in a list of lists and passes it to
>:direct-slot argument of a ENSURE-CLASS. For example
>
>  :my-func #'foo

I assume you're referring to a slot defined as:

   (my-func (:initarg :my-func) (:initform #'foo))

>becomes
>  :direct-slots
>  (list 
>    (list .... ':my-func '#'foo .....)
>    )
>
>Of course when I try to get type of :my-func slot I see CONS instead of
>function. Is it possible to have function there ? E.g.  prevent
>quoting or something else solution ? Could you advise something.

In order to preserve proper lexical scoping, it must wrap the form in a
lambda expression:

(list ... ':my-func #'(lambda () #'foo) ...)

When the initform is needed, the allocator will FUNCALL this.

-- 
Barry Margolin, ······@genuity.net
Genuity, 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: Vladimir Zolotykh
Subject: Re: DEFCLASS question
Date: 
Message-ID: <3D005AB3.3E90BCFF@eurocom.od.ua>
Barry Margolin wrote:
> 
> In article <················@eurocom.od.ua>,
> Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
> >Let me consider DEFCLASS macro. For my question it is essential that
> >it arranges its arguments in a list of lists and passes it to
> >:direct-slot argument of a ENSURE-CLASS. For example
> >
> >  :my-func #'foo
> 
> I assume you're referring to a slot defined as:
> 
>    (my-func (:initarg :my-func) (:initform #'foo))

No this is not :initform. Metaclass was introduced, slot definition
changed, so :my-func argument is simply stored as a value in a slot object.
Some after it is tried to be used. It is of type CONS because DEFCLASS quoted it.
I'm not sure how all this should be implemented properly. For example
I could use

  :my-fun #.(function foo)

But this seems inconvenient for several reasons. Loss of lexical environment
for example.


-- 
Vladimir Zolotykh
From: Barry Margolin
Subject: Re: DEFCLASS question
Date: 
Message-ID: <d84M8.5$rs6.298@paloalto-snr2.gtei.net>
In article <·················@eurocom.od.ua>,
Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
>Barry Margolin wrote:
>> 
>> In article <················@eurocom.od.ua>,
>> Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
>> >Let me consider DEFCLASS macro. For my question it is essential that
>> >it arranges its arguments in a list of lists and passes it to
>> >:direct-slot argument of a ENSURE-CLASS. For example
>> >
>> >  :my-func #'foo
>> 
>> I assume you're referring to a slot defined as:
>> 
>>    (my-func (:initarg :my-func) (:initform #'foo))
>
>No this is not :initform. Metaclass was introduced, slot definition
>changed, so :my-func argument is simply stored as a value in a slot object.
>Some after it is tried to be used. It is of type CONS because DEFCLASS quoted it.

If it did, then it must be because the that value is being used in a
context that's not evaluated.  Unfortunately, the language doesn't provide
a way to enter functions as literal objects, only as the result of
evaluation of FUNCTION forms (which is what #'foo expands to).  It's being
quoted to ensure that it doesn't get evaluated.

>I'm not sure how all this should be implemented properly. For example
>I could use
>
>  :my-fun #.(function foo)
>
>But this seems inconvenient for several reasons. Loss of lexical environment
>for example.

It also may not work if you compile the file; from CLHS 3.2.4.2.2:
"Functions are not externalizable objects".

Maybe there's a problem with the way you've defined your metaclass.  It's
hard to provide concrete suggestions without more context showing how the
expression is being used.

-- 
Barry Margolin, ······@genuity.net
Genuity, 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: Vladimir Zolotykh
Subject: Re: DEFCLASS question
Date: 
Message-ID: <3D009CC5.A0A8D54D@eurocom.od.ua>
Here is the solution which satisifies me somehow though I'd prefer to
avoid EVAL in it. Also I hope this explains clear enough the problem
itself (I'm afraind I didn't state it properly in the initial
posting).

  (defmacro def-my-class (class supers slots &rest options)
    `(defclass ,class ,supers 
	,(loop for slot in slots
	    collect 
	      (cons (car slot) 
		    (loop for (key value) on (cdr slot) by #'cddr
			if (eq key :my-func)
			nconc (list key (eval value))
			else nconc (list key value))))
	,@options
        (:metaclass my-metaclass)))

I'm still seeking for better solution.

Barry Margolin wrote:
> 
> In article <················@eurocom.od.ua>,
> Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
> >Let me consider DEFCLASS macro. For my question it is essential that
> >it arranges its arguments in a list of lists and passes it to
> >:direct-slot argument of a ENSURE-CLASS. For example
> >
> >  :my-func #'foo
> 
> I assume you're referring to a slot defined as:
> 
>    (my-func (:initarg :my-func) (:initform #'foo))

-- 
Vladimir Zolotykh
From: Barry Margolin
Subject: Re: DEFCLASS question
Date: 
Message-ID: <fj4M8.6$rs6.310@paloalto-snr2.gtei.net>
In article <·················@eurocom.od.ua>,
Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
>Here is the solution which satisifies me somehow though I'd prefer to
>avoid EVAL in it. Also I hope this explains clear enough the problem
>itself (I'm afraind I didn't state it properly in the initial
>posting).
>
>  (defmacro def-my-class (class supers slots &rest options)
>    `(defclass ,class ,supers 
>	,(loop for slot in slots
>	    collect 
>	      (cons (car slot) 
>		    (loop for (key value) on (cdr slot) by #'cddr
>			if (eq key :my-func)
>			nconc (list key (eval value))
>			else nconc (list key value))))
>	,@options
>        (:metaclass my-metaclass)))
>
>I'm still seeking for better solution.

Using EVAL in a macro definition is almost always wrong.  First of all, it
breaks lexical scoping, which was something you indicated you were
concerned with in another post.  Second, it evaluates the expression at
macro-expansion time (e.g. when you compile the file), not run-time; at
that time, the function may not even exist.

I'm not an expert on the MOP, but it may be the case that DEFCLASS doesn't
provide any way for the metaclass to customize the way it expands.  In that
case, you may need to define you DEF-MY-CLASS macro so that it expands
directly into the appropriate call to ENSURE-CLASS, so that the appropriate
arguments are still evaluated.

-- 
Barry Margolin, ······@genuity.net
Genuity, 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: Vladimir Zolotykh
Subject: Re: DEFCLASS question
Date: 
Message-ID: <3D020B61.95FAC238@eurocom.od.ua>
Thank you Barry, Kenny.

I clearly see the problems with using an EVAL. I agreed this should be
avoided.

Writing my own DEFCLASS macro suits me best for now, though I hardly
can imagine how it could be written in a portable manner.

I've tried to use symbol (as Kenny suggested) instead of function 
object and get its FUNCITON-VALUE or just FUNCALL or APPLY it.
This works of course but temptation to use #' was strong. I mean 
when the user sees that something (slot for example) could be used
as a function he/she for certain could use #' (unless was explicitly
told against).

-- 
Vladimir Zolotykh
From: Kenny Tilton
Subject: Re: DEFCLASS question
Date: 
Message-ID: <3D0221B3.FF165853@nyc.rr.com>
Vladimir Zolotykh wrote:
> 
> I mean
> when the user sees that something (slot for example) could be used
> as a function he/she for certain could use #' (unless was explicitly
> told against).

Well, consider this (valid using ACL's persistent CLOS AllegroStore
package):

(defclass order ()
  ((customer :initarg :customer :initform nil
             :inverse find-orders-for-customer ;; AStore makes this into
a generic function
             :reader order-customer ;; this and next of course also
become GFs
             :writer set-order-customer))
  (:metaclass persistent-standard-class)))

No #' stuff at all. Come to think of it, might as well just support:

  (....   :my-func foo ...) ;; my suggestion of 'foo (quoting the func
name) was daffy

When extending CL I think the user benefits if you can extend in ways
consistent with CL, so in fact:

  (  :my-func #'foo )

... as reasonable as it looks, would be a mistake.

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
""Well, I've wrestled with reality for thirty-five years, Doctor, 
  and I'm happy to state I finally won out over it.""
                                                  Elwood P. Dowd
From: Vladimir Zolotykh
Subject: Re: DEFCLASS question
Date: 
Message-ID: <3D022840.2AA8E826@eurocom.od.ua>
Yes this changed my mind. Let it be a symbol or a list
like (lambda (x) (1+ x) which equally well could be funcalled.
This is much more easy to implement.

Kenny Tilton wrote:
> 
> Vladimir Zolotykh wrote:
> >
> > I mean
> > when the user sees that something (slot for example) could be used
> > as a function he/she for certain could use #' (unless was explicitly
> > told against).
> 
> Well, consider this (valid using ACL's persistent CLOS AllegroStore
> package):
> 
> (defclass order ()
>   ((customer :initarg :customer :initform nil
>              :inverse find-orders-for-customer ;; AStore makes this into
> a generic function
>              :reader order-customer ;; this and next of course also
> become GFs
>              :writer set-order-customer))
>   (:metaclass persistent-standard-class)))
> 
> No #' stuff at all. Come to think of it, might as well just support:
> 
>   (....   :my-func foo ...) ;; my suggestion of 'foo (quoting the func
> name) was daffy
> 
> When extending CL I think the user benefits if you can extend in ways
> consistent with CL, so in fact:
> 
>   (  :my-func #'foo )
> 
> ... as reasonable as it looks, would be a mistake.
> 
> --
> 
>  kenny tilton
>  clinisys, inc
>  ---------------------------------------------------------------
> ""Well, I've wrestled with reality for thirty-five years, Doctor,
>   and I'm happy to state I finally won out over it.""
>                                                   Elwood P. Dowd

-- 
Vladimir Zolotykh
From: Tim Moore
Subject: Re: DEFCLASS question
Date: 
Message-ID: <adtlf1$983$0@216.39.145.192>
On Sat, 08 Jun 2002 16:49:21 +0300, Vladimir Zolotykh <······@eurocom.od.ua>
 wrote:

>Thank you Barry, Kenny.
>
>I clearly see the problems with using an EVAL. I agreed this should be
>avoided.
>
>Writing my own DEFCLASS macro suits me best for now, though I hardly
>can imagine how it could be written in a portable manner.
>
>I've tried to use symbol (as Kenny suggested) instead of function 
>object and get its FUNCITON-VALUE or just FUNCALL or APPLY it.
>This works of course but temptation to use #' was strong. I mean 
>when the user sees that something (slot for example) could be used
>as a function he/she for certain could use #' (unless was explicitly
>told against).

You might think a bit about whether your metaclass option makes more
sense as a class-allocated slot.  If so you could write a wrapper
around DEFMACRO that's a lot less work than going all the way to
ENSURE-CLASS: it would just transform your "option" into a
class-allocated slot with an initform that's the value supplied by the
user.  That way your users can use #' syntax, refer to stuff in a
local environment, etc.

If what you want is actually a slot option, you're kind of hosed
unless you do a lot more work.

Tim
From: Vladimir Zolotykh
Subject: Re: DEFCLASS question
Date: 
Message-ID: <3D039634.E941D306@eurocom.od.ua>
Tim Moore:
> 
> You might think a bit about whether your metaclass option makes more
> sense as a class-allocated slot.  If so you could write a wrapper
> around DEFMACRO that's a lot less work than going all the way to
         ^^
Don't you mean DEFCLASS here ?

> ENSURE-CLASS: it would just transform your "option" into a
> class-allocated slot with an initform that's the value supplied by the
> user.  That way your users can use #' syntax, refer to stuff in a
> local environment, etc.

It would be the best, unfortunately it is really a slot option. Class
can have a number of such slots and each one could have :my-func.
From: Tim Moore
Subject: Re: DEFCLASS question
Date: 
Message-ID: <ae1att$h90$0@216.39.145.192>
On Sun, 09 Jun 2002 21:53:56 +0400, Vladimir Zolotykh <······@eurocom.od.ua>
 wrote:
>
>
>Tim Moore:
>> 
>> You might think a bit about whether your metaclass option makes more
>> sense as a class-allocated slot.  If so you could write a wrapper
>> around DEFMACRO that's a lot less work than going all the way to
>         ^^
>Don't you mean DEFCLASS here ?
Yup.
>> ENSURE-CLASS: it would just transform your "option" into a
>> class-allocated slot with an initform that's the value supplied by the
>> user.  That way your users can use #' syntax, refer to stuff in a
>> local environment, etc.
>
>It would be the best, unfortunately it is really a slot option. Class
>can have a number of such slots and each one could have :my-func.

Oh well...
Tim
From: Kenny Tilton
Subject: Re: DEFCLASS question
Date: 
Message-ID: <3D00CD5C.ECB9CE5F@nyc.rr.com>
Vladimir Zolotykh wrote:
> 
> Let me consider DEFCLASS macro. For my question it is essential that
> it arranges its arguments in a list of lists and passes it to
> :direct-slot argument of a ENSURE-CLASS. For example
> 
>   :my-func #'foo
> 
> becomes
>   :direct-slots
>   (list
>     (list .... ':my-func '#'foo .....)
>     )
> 
> Of course when I try to get type of :my-func slot I see CONS instead of
> function. Is it possible to have function there ? E.g.  prevent
> quoting or something else solution ? Could you advise something.

I am puzzled. Under ACL5, when I compile:

  (defmodel Model ()
    ((mdValue :initform nil :accessor mdvalue :initarg :mdValue
:semaphor #'hi-mom)))

...where semaphor is a custom slot option like your :my-func, my
debugging ensure-class-using-class method:


   (defmethod ensure-class-using-class ((class modelclass) name &key
direct-default-initargs direct-slots
                                     direct-superclasses name metaclass
                                     &allow-other-keys)
     (declare (ignorable direct-default-initargs direct-slots
                      direct-superclasses name metaclass))
     (trc "direct slots" direct-slots)
     (dolist (ds direct-slots)
        (trc "ds" ds)))


...produces this output:

0> 16.81 direct slots ((:NAME MDVALUE :INITFORM NIL :INITFUNCTION
#<Function FALSE> :INITARGS (:MDVALUE) :READERS (MDVALUE) :WRITERS
((SETF MDVALUE)) :SEMAPHOR #'HI-MOM))
0> 16.81 ds (:NAME MDVALUE :INITFORM NIL :INITFUNCTION #<Function FALSE>
:INITARGS (:MDVALUE) :READERS (MDVALUE) :WRITERS ((SETF MDVALUE))
:SEMAPHOR #'HI-MOM)

...which looks dandy to me.

You said you were poking around in ensure-class... true that? maybe you
should be specializing e-c-u-c? Mind you, none of this is necessary just
to get the value #'foo into the my-func slot of your DSD. The trick is
just to make sure you tell the MOP to use your direct slot class, which
we covered before.

Vlad, I got lotsa time on my hands just now. Just yell if you need me to
carve out a small standalone working example.

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
""Well, I've wrestled with reality for thirty-five years, Doctor, 
  and I'm happy to state I finally won out over it.""
                                                  Elwood P. Dowd
From: Barry Margolin
Subject: Re: DEFCLASS question
Date: 
Message-ID: <Il4M8.1$eZ1.289@paloalto-snr1.gtei.net>
In article <·················@nyc.rr.com>,
Kenny Tilton  <·······@nyc.rr.com> wrote:
>...produces this output:
>
>0> 16.81 direct slots ((:NAME MDVALUE :INITFORM NIL :INITFUNCTION
>#<Function FALSE> :INITARGS (:MDVALUE) :READERS (MDVALUE) :WRITERS
>((SETF MDVALUE)) :SEMAPHOR #'HI-MOM))
>0> 16.81 ds (:NAME MDVALUE :INITFORM NIL :INITFUNCTION #<Function FALSE>
>:INITARGS (:MDVALUE) :READERS (MDVALUE) :WRITERS ((SETF MDVALUE))
>:SEMAPHOR #'HI-MOM)
>
>...which looks dandy to me.

No, it's not dandy.  If it worked as the OP intended, the output would have
:SEMAPHOR #<Function HI-MOM> rather than :SEMPAHOR #'HI-MOM.  The latter
indicates that the list (FUNCTION HI-MOM) is in the :SEMAPHOR option,
rather than the function itself.

-- 
Barry Margolin, ······@genuity.net
Genuity, 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: DEFCLASS question
Date: 
Message-ID: <3D00DC7C.249127C@nyc.rr.com>
Barry Margolin wrote:
> 
> In article <·················@nyc.rr.com>,
> Kenny Tilton  <·······@nyc.rr.com> wrote:
> >...produces this output:
> >
> >0> 16.81 direct slots ((:NAME MDVALUE :INITFORM NIL :INITFUNCTION
> >#<Function FALSE> :INITARGS (:MDVALUE) :READERS (MDVALUE) :WRITERS
> >((SETF MDVALUE)) :SEMAPHOR #'HI-MOM))
> >0> 16.81 ds (:NAME MDVALUE :INITFORM NIL :INITFUNCTION #<Function FALSE>
> >:INITARGS (:MDVALUE) :READERS (MDVALUE) :WRITERS ((SETF MDVALUE))
> >:SEMAPHOR #'HI-MOM)
> >
> >...which looks dandy to me.
> 
> No, it's not dandy.  If it worked as the OP intended, the output would have
> :SEMAPHOR #<Function HI-MOM> rather than :SEMPAHOR #'HI-MOM.  The latter
> indicates that the list (FUNCTION HI-MOM) is in the :SEMAPHOR option,
> rather than the function itself.

Ok, I see. My bad. I am accustomed to #'foo appearing where it would be
evaluated, but defclass does not evaluate the option arguments.

Vlad, as Barry said in another reply, you should not try to make a
function instance part of a class definition. How about just coding:

  (defclass wawa () ((woohoo :initarg :woohoo :my-func 'foo))(:metaclass
vladimir-class))

...and using (symbol-function (my-func <dsd>)) to get the function when
you need it?

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
""Well, I've wrestled with reality for thirty-five years, Doctor, 
  and I'm happy to state I finally won out over it.""
                                                  Elwood P. Dowd