From: ····@att.net
Subject: CLOS class in different packages
Date: 
Message-ID: <1165281428.703266.7000@l12g2000cwl.googlegroups.com>
Hi,

I have a parent CLOS class and related generics defined in one
package, and have classes derived from the parent defined in other
packages.  In order to access slots defined in the parent, from the
derived class, I had to either:

1. export them from the parent class, or
2. qualify them using the package name, e.g. parent::last-name

Option 1 seems to sort of "disconnect" the slot from it's class, and
option 2 seems somewhat clumsy.

Is there another option?

Obviously if the parent and child classes are defined in the same
package everything is "easier".

;; defined in package parent-package
(defclass parent ()
  ((last-name
   :initarg :last-name
   :initform (error "last-name required for parent"))))

;; defined in package child-package
(defclass child (parent) ())

(defmethod display-last-name ((parent child))
  (with-slots (parent-package::last-name) parent
      (print parent-package::last-name)))

Many thanks!

Cheers,
David

From: Zach Beane
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <m3psazb0a6.fsf@unnamed.xach.com>
····@att.net writes:

> Hi,
> 
> I have a parent CLOS class and related generics defined in one
> package, and have classes derived from the parent defined in other
> packages.  In order to access slots defined in the parent, from the
> derived class, I had to either:
> 
> 1. export them from the parent class, or
> 2. qualify them using the package name, e.g. parent::last-name
> 
> Option 1 seems to sort of "disconnect" the slot from it's class, and
> option 2 seems somewhat clumsy.

Don't feel that way about option 1. The way to indicate a symbol is
for public consumption is by exporting it from its package. That means
function names, class names, macro names, slot names, etc.

Zach
From: Andrew Reilly
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <4tk721F146nohU1@mid.individual.net>
On Mon, 04 Dec 2006 20:26:41 -0500, Zach Beane wrote:

> ····@att.net writes:
> 
>> Hi,
>> 
>> I have a parent CLOS class and related generics defined in one
>> package, and have classes derived from the parent defined in other
>> packages.  In order to access slots defined in the parent, from the
>> derived class, I had to either:
>> 
>> 1. export them from the parent class, or
>> 2. qualify them using the package name, e.g. parent::last-name
>> 
>> Option 1 seems to sort of "disconnect" the slot from it's class, and
>> option 2 seems somewhat clumsy.
> 
> Don't feel that way about option 1. The way to indicate a symbol is
> for public consumption is by exporting it from its package. That means
> function names, class names, macro names, slot names, etc.

But use in a derived class isn't really "public consumption": an instance
of a derived class *is* an instance of the parent class (through
inheritance), in most object systems that I know about.  So consequently
the methods on the derived class get to muck with the internals of the
parent class as though they were their own (because they are).  Is that
not the case with CLOS?

[In response to another poster: I don't think that this question has
anything to do with the C++ "friend" notion; more the distinction between
public/protected/private.]

-- 
Andrew
From: Ken Tilton
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <1P5dh.118$Ty4.6@newsfe11.lga>
Andrew Reilly wrote:
> On Mon, 04 Dec 2006 20:26:41 -0500, Zach Beane wrote:
> 
> 
>>····@att.net writes:
>>
>>
>>>Hi,
>>>
>>>I have a parent CLOS class and related generics defined in one
>>>package, and have classes derived from the parent defined in other
>>>packages.  In order to access slots defined in the parent, from the
>>>derived class, I had to either:
>>>
>>>1. export them from the parent class, or
>>>2. qualify them using the package name, e.g. parent::last-name
>>>
>>>Option 1 seems to sort of "disconnect" the slot from it's class, and
>>>option 2 seems somewhat clumsy.
>>
>>Don't feel that way about option 1. The way to indicate a symbol is
>>for public consumption is by exporting it from its package. That means
>>function names, class names, macro names, slot names, etc.
> 
> 
> But use in a derived class isn't really "public consumption": an instance
> of a derived class *is* an instance of the parent class (through
> inheritance), in most object systems that I know about.  So consequently
> the methods on the derived class get to muck with the internals of the
> parent class as though they were their own (because they are).  Is that
> not the case with CLOS?

<cough> But the subclass is being defined in a different package, so 
somewhere in your mind you have crossed a boundary, you are just sort 
kind of "ambivalent" about it. You think of all subclasses as being 
internal to their superclasses, yet you have one in a different package.

This is not a CLOS or language syntax issue, you are just confused. It 
happens. :)

anothe poster

-- 
Algebra: http://www.tilton-technology.com/LispNycAlgebra1.htm

"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

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Tim Bradshaw
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <el397v$3u2$1$8300dec7@news.demon.co.uk>
On 2006-12-05 03:23:45 +0000, Andrew Reilly 
<···············@areilly.bpc-users.org> said:

> But use in a derived class isn't really "public consumption": an instance
> of a derived class *is* an instance of the parent class (through
> inheritance), in most object systems that I know about.  So consequently
> the methods on the derived class get to muck with the internals of the
> parent class as though they were their own (because they are).  Is that
> not the case with CLOS?

No.  Nor is it the case with Java, say.  You'd have to declare the 
member in the parent as protected I think.  The CL package system 
really only has public and private equivalents (and doesn't tie in to 
the class structure): you'd have to implement the equivalent of 
protected yourself (which you can do easily enough).

--tim
From: Barry Margolin
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <barmar-5856DC.21191805122006@comcast.dca.giganews.com>
In article <···············@mid.individual.net>,
 Andrew Reilly <···············@areilly.bpc-users.org> wrote:

> On Mon, 04 Dec 2006 20:26:41 -0500, Zach Beane wrote:
> 
> > ····@att.net writes:
> > 
> >> Hi,
> >> 
> >> I have a parent CLOS class and related generics defined in one
> >> package, and have classes derived from the parent defined in other
> >> packages.  In order to access slots defined in the parent, from the
> >> derived class, I had to either:
> >> 
> >> 1. export them from the parent class, or
> >> 2. qualify them using the package name, e.g. parent::last-name
> >> 
> >> Option 1 seems to sort of "disconnect" the slot from it's class, and
> >> option 2 seems somewhat clumsy.
> > 
> > Don't feel that way about option 1. The way to indicate a symbol is
> > for public consumption is by exporting it from its package. That means
> > function names, class names, macro names, slot names, etc.
> 
> But use in a derived class isn't really "public consumption": an instance
> of a derived class *is* an instance of the parent class (through
> inheritance), in most object systems that I know about.  So consequently
> the methods on the derived class get to muck with the internals of the
> parent class as though they were their own (because they are).  Is that
> not the case with CLOS?

Unlike many other OO systems, CLOS doesn't use classes as an information 
hiding mechanism.  There's no such thing as public/protected/private 
methods or slots -- everything is accessible from anywhere.  Classes are 
just an abstraction mechanism, while packages are used for visibility 
control.

If two classes are so closely related that they should have easier 
access to each other's attributes than other code does, they should 
probably be in the same package.

Another thing you can do, though, is explicitly import the symbols from 
the parent package to the child package.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Barry Margolin
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <barmar-0C28DB.20342704122006@comcast.dca.giganews.com>
In article <······················@l12g2000cwl.googlegroups.com>,
 ····@att.net wrote:

> Hi,
> 
> I have a parent CLOS class and related generics defined in one
> package, and have classes derived from the parent defined in other
> packages.  In order to access slots defined in the parent, from the
> derived class, I had to either:
> 
> 1. export them from the parent class, or
> 2. qualify them using the package name, e.g. parent::last-name
> 
> Option 1 seems to sort of "disconnect" the slot from it's class, and
> option 2 seems somewhat clumsy.
> 
> Is there another option?

#1 is probably the correct way.  If you want code in other packages to 
be able to access something in your package, the proper thing to do is 
export it.  There's no special relationship between CLOS classes and 
packages, so there's no way around this just for parent/child classes.

Remember, packages just deal with symbols, not with what those symbols 
represent.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Ken Tilton
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <784dh.206$%57.42@newsfe09.lga>
····@att.net wrote:
> Hi,
> 
> I have a parent CLOS class and related generics defined in one
> package, and have classes derived from the parent defined in other
> packages.  In order to access slots defined in the parent, from the
> derived class, I had to either:
> 
> 1. export them from the parent class, or
> 2. qualify them using the package name, e.g. parent::last-name
> 
> Option 1 seems to sort of "disconnect" the slot from it's class, and

"seems to sort of" IIANM translates as "does not" (and then you can take 
the I-do-not-really-mean-it antlers off disconnect).

Note that you /do/ "desire to access [the] slots" from a different 
package. Why making public something you want to be public constitutes 
"disconnect" needs clarification. :)

> option 2 seems somewhat clumsy.
> 
> Is there another option?

Are you looking for that "friends" stuff from C++ (if I have that right, 
unless it was Java <g>). This is Lisp, we just shoot from the hip and do 
not worry about that stuff.

hth,kt

-- 
Algebra: http://www.tilton-technology.com/LispNycAlgebra1.htm

"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

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Pascal Costanza
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <4tkp00F13pg04U1@mid.individual.net>
····@att.net wrote:
> Hi,
> 
> I have a parent CLOS class and related generics defined in one
> package, and have classes derived from the parent defined in other
> packages.  In order to access slots defined in the parent, from the
> derived class, I had to either:
> 
> 1. export them from the parent class, or
> 2. qualify them using the package name, e.g. parent::last-name
> 
> Option 1 seems to sort of "disconnect" the slot from it's class, and
> option 2 seems somewhat clumsy.
> 
> Is there another option?

Yes: In general, it is better not to access slots directly via 
slot-value and the likes, but to rather go through accessor functions, 
which you can declare with :reader, :writer and :accessor options in the 
slot definitions. Just export the names of those accessor functions. 
This has the advantage that you can better control whether client code 
is allowed to only read or additionally write slots as well. It also has 
the advantage that you can define :before/:after/:around methods on such 
accessors that do additional things whenever such slots are accessed, 
and be sure that they are actually triggered. Furthermore, it gives you 
the option to later change your mind and, for example, instead of 
representing an attribute of a class as a slot turn it into a computed 
attribute. The functional interface that readers and writers provide 
don't need to be changed in that case, whereas access via slot-value 
becomes invalid then.

Finally, in most CLOS implementations, accessing slots via accessor 
functions is typically actually faster than with slot-value etc. (but at 
least not slower).

You should really leave access via slot-value etc. to low-level 
functionality that is close to the original class definition when you, 
for example, want to circumvent :before/:after/:around methods on accessors.

For that matter, it is probably a good idea that accessor functions have 
different names than the slots themselves.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Madhu
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <m3vekqs3u8.fsf@robolove.meer.net>
Helu
* ····@att.net <······················@l12g2000cwl.XXXXXX.com> :
| I have a parent CLOS class and related generics defined in one
| package, and have classes derived from the parent defined in other
| packages.  In order to access slots defined in the parent, from the
| derived class, I had to either:
|
| 1. export them from the parent class, or
| 2. qualify them using the package name, e.g. parent::last-name
|
| Option 1 seems to sort of "disconnect" the slot from it's class, and
| option 2 seems somewhat clumsy.
|
| Is there another option?

There is this ugly option:

(defmacro with-pkg-slots ((&rest slot-vars) obj pkg  &body body)
  `(let ,(loop for slot-var in slot-vars
               collect (list slot-var
                             `(slot-value ,obj',(find-symbol
                                                 (symbol-name slot-var) pkg))))
     ,@body))

| Obviously if the parent and child classes are defined in the same
| package everything is "easier".
|
| ;; defined in package parent-package
| (defclass parent ()
|   ((last-name
|    :initarg :last-name
|    :initform (error "last-name required for parent"))))
|
| ;; defined in package child-package
| (defclass child (parent) ())
|
| (defmethod display-last-name ((parent child))
|   (with-slots (parent-package::last-name) parent
|       (print parent-package::last-name)))

(defmethod display-last-name ((parent child))
  (with-pkg-slots (last-name) parent :parent-package
      (print last-name)))

(macroexpand-1
 '(with-pkg-slots (last-name) parent :parent-package
   (print last-name)))

=> (LET ((LAST-NAME (SLOT-VALUE PARENT 'PARENT-PACKAGE::LAST-NAME)))
     (PRINT LAST-NAME)), T

But I wouldnt recommended using it except for rapid prototyping.
Later, its better to think long and hard about your symbols and
package and boundaries, and revert to WITH-SLOTS after fixing the
package structures.

-- Madhu
From: Madhu
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <m3lklms2gl.fsf@robolove.meer.net>
[Fixing a bug]

* Madhu  <··············@robolove.meer.net> :

> * ····@att.net <······················@l12g2000cwl.XXXXXX.com> :
>
> | I have a parent CLOS class and related generics defined in one
> | package, and have classes derived from the parent defined in other
> | packages.  In order to access slots defined in the parent, from the
> | derived class, I had to either:
> |
> | 1. export them from the parent class, or
> | 2. qualify them using the package name, e.g. parent::last-name
> |
> | Option 1 seems to sort of "disconnect" the slot from it's class, and
> | option 2 seems somewhat clumsy.
> |
> | Is there another option?
>
> There is this ugly option:
>
> (defmacro with-pkg-slots ((&rest slot-vars) obj pkg  &body body)
>   `(let ,(loop for slot-var in slot-vars
>                collect (list slot-var
>                           `(slot-value ,obj',(find-symbol
>                                              (symbol-name slot-var) pkg))))
>      ,@body))
>

Unfortunately that does not capture the semantics of WITH-SLOTS: if
you like using SETQ (Like I do) on the variables introduced. The
following works better, I think.

(defmacro with-pkg-slots ((&rest slot-vars) obj pkg  &body body)
  "PKG is a package designator (evaluated) denoting the package
in which slots-vars are looked up."
  (let ((objvar (gensym)))
    `(let ((,objvar ,obj))
       (declare (ignorable ,objvar))
       (symbol-macrolet 
	   ,(loop for slot-var in slot-vars
		  collect (list slot-var `(slot-value ,objvar ',(find-symbol (symbol-name slot-var) pkg))))
	 ,@body))))


> | Obviously if the parent and child classes are defined in the same
> | package everything is "easier".
> |
> | ;; defined in package parent-package
> | (defclass parent ()
> |   ((last-name
> |    :initarg :last-name
> |    :initform (error "last-name required for parent"))))
> |
> | ;; defined in package child-package
> | (defclass child (parent) ())
> |
> | (defmethod display-last-name ((parent child))
> |   (with-slots (parent-package::last-name) parent
> |       (print parent-package::last-name)))
>
> (defmethod display-last-name ((parent child))
>   (with-pkg-slots (last-name) parent :parent-package
>       (print last-name)))
>
> (macroexpand-1
>  '(with-pkg-slots (last-name) parent :parent-package
>    (print last-name)))
>
> => (LET ((LAST-NAME (SLOT-VALUE PARENT 'PARENT-PACKAGE::LAST-NAME)))
>      (PRINT LAST-NAME)), T
>

This now reads:
=> (LET ((#:G8060 PARENT))
     (DECLARE (IGNORABLE #:G8060))
     (SYMBOL-MACROLET ((LAST-NAME
                        (SLOT-VALUE #:G8060 'PARENT-PACKAGE::LAST-NAME)))
       (PRINT LAST-NAME))), T

> But I wouldnt recommended using it except for rapid prototyping.
> Later, its better to think long and hard about your symbols and
> package and boundaries, and revert to WITH-SLOTS after fixing the
> package structures.
>

-- Madhu
From: Madhu
Subject: Re: CLOS class in different packages
Date: 
Message-ID: <m3hcwas0qm.fsf@robolove.meer.net>
Helu again,
* ····@att.net <······················@l12g2000cwl.XXXXXX.com> :
| Hi,
| ;; defined in package parent-package
| (defclass parent ()
|   ((last-name
|    :initarg :last-name
|    :initform (error "last-name required for parent"))))
|
| ;; defined in package child-package
| (defclass child (parent) ())
|
| (defmethod display-last-name ((parent child))
|   (with-slots (parent-package::last-name) parent
|       (print parent-package::last-name)))

Note WITH-SLOTS also allows this syntax:

(with-slots ((last-name parent-package::last-name)) parent
    (print last-name))

--
Madhu