From: Masoud Pirnazar
Subject: Re: What are some ways of packaging a class and its methods?
Date: 
Message-ID: <38B1AE8A.9B2C8A23@poboxes.com>
>Define a package and export your functions and methods
>that define the protocol for the class.
>Maybe also the class name.
This is what I was asking:  what has to be exported.

1.  Some of the methods use symbols such as 'first and 'last.  I can export
these, but they may pollute the importer's namespace (i.e. if the importing
package already has a 'first).  Instead, I can use :first and :last, or
require the caller to use 'cons2:first.
2. class definitions create additional symbols (e.g. slot names).  Some
implementations (I think cmucl) disallow keywords for slot names.  If others
have actually created classes within packages, they would have run into these
issues, and have some standard solutions for them.

I'm looking for some example packaged modules to use as paradigms when
creating new modules.

If you have any such examples, I'd appreciate looking at them.  Meanwhile, I'm
looking into existing lisp programs to see how they package their modules.



Rainer Joswig wrote:

> In article <·················@poboxes.com>, Masoud Pirnazar
> <·················@poboxes.com> wrote:
>
> > Would you do in-package?  Does the defclass need to have some symbols
> > made public?
>
> Define a package and export your functions and methods
> that define the protocol for the class.
> Maybe also the class name.
>
> (Btw., "The Art of the Metaobject Protocol" shows
> a lot about CLOS programming style. Beautiful book.)
>
> > What .lisp files could you put various definitions in?
>
> One file for such a "small" functionality is enough.
> Otherwise you would need:
>
> - Logical Pathname
> - System
> - Documentation
> - Code
> -- Package
> -- Implementation
> -- Examples and Tests
> -- UI
>
> > Here is a simple sample to use:
> >
> > (defclass c-cons2 ()
> >   (
> >    (prev :initarg :prev)
> >    (next :initarg :next)
> >    (data :initform nil :initarg :data)
> >    ))
>
> Don't put parentheses on otherwise empty lines.
> Just don't care about them. Write compact
> code that doesn't waste space.
>
> > ;; get 'prev or 'next node
> > (defmethod cons2-get-node ((n c-cons2) which) (slot-value n which))
>
> I guess you could get some optimization by rewriting it.
>
> Why not use the class reader methods in the first place?
>
> > ;; add new node, return its position
> > (defmethod cons2-add-node ( (new-node c-cons2) (at c-cons2) (where
> > symbol))
> >   (cond ((eq where 'before) (cons2-insert-node-0 new-node (slot-value at
> > 'prev) at))
> >  ((eq where 'after ) (cons2-insert-node-0 new-node at (slot-value at
> > 'next))))
> >   new-node
> >   )
>
> You can get rid of the COND by dispatching over the symbols.
> Otherwise I'd prefer ECASE.
>
> > ;; create dummy node for a list
> > (defmethod cons2-make-dummy-node ()
> >   (make-instance 'c-cons2 :data nil))
>
> Data is already initialized to NIL in the class definition.
>
> > (defmethod print-object ((n c-cons2) stream)
> >   (format stream "(c-cons2 ~a ~a ~a)" (slot-value n 'data) (slot-value n
> > 'prev) (slot-value n 'next) ))
>
> Maybe you want to use PRINT-UNREADABLE-OBJECT.
> Also watch for circularities...
>
> Rainer Joswig, ISION Internet AG, Harburger Schlossstrasse 1,
> 21079 Hamburg, Germany, Tel: +49 40 77175 226
> Email: ·············@ision.de , WWW: http://www.ision.de/

From: Pierre R. Mai
Subject: Re: What are some ways of packaging a class and its methods?
Date: 
Message-ID: <87wvny5gby.fsf@orion.dent.isdn.cs.tu-berlin.de>
Masoud Pirnazar <··········@poboxes.com> writes:

> >Define a package and export your functions and methods
> >that define the protocol for the class.
> >Maybe also the class name.
> This is what I was asking:  what has to be exported.

Normally you export everything that is part of the published API of
your library.

> 1.  Some of the methods use symbols such as 'first and 'last.  I can export
> these, but they may pollute the importer's namespace (i.e. if the importing
> package already has a 'first).  Instead, I can use :first and :last, or
> require the caller to use 'cons2:first.

For what do you use symbols like 'first and 'last in your API?  If the 
symbols are used as keywords, they should be keywords, i.e. use :first 
and :last instead.  But dispatching on keywords is only useful in very 
limited situations, IMHO, so maybe there is a much better way to
achieve what you want to do?

Also note that:

a) 'cl:first and 'cl:last are present in the COMMON-LISP package,
   which most packages use by default (including your cons2 package),
   so that (eq cons2::first cl::first).  Hence exporting 'first from
   cons2 is not really necessary, useful or good.

b) Also note that exporting a symbol is necessary to reference the
   symbol with  the package:symbol syntax.  To use an unexported
   symbol, you have to use package::symbol.  Using unexported symbols
   is considered rude, and should only ever be done if there is no
   other way to achieve your goals, and you accept the risk that this
   implies (generally the implementor of the foreign package should
   feel free to change the unexported parts of his package any way he
   likes).

c) This issue is only indirectly related to the possibility of leaving 
   off the package prefix.  This is achieved by useing (via
   use-package or the :use clause of defpackage) the another package,
   in which case all exported symbols will be reachable without the
   package prefix.


> 2. class definitions create additional symbols (e.g. slot names).  Some
> implementations (I think cmucl) disallow keywords for slot names.  If others
> have actually created classes within packages, they would have run into these
> issues, and have some standard solutions for them.

Class definitions don't create slot name symbols, you supply the slot
name symbols.  You shouldn't expose the names of your slots by
exporting them, since basically it's none of the users business how
you call your slots, or that certain attributes of your class are
indeed implemented as slots.  Users should use the documented,
exported accessors, writers or readers to access and change
attributes.

> I'm looking for some example packaged modules to use as paradigms when
> creating new modules.

Take a look at some of the modules/libraries available for CL.  See
for example the CommonSQL interface that Harlequin offers for their
LispWorks products (see http://www.harlequin.com/).  Or you might take 
a look at my implementation of a subset of CommonSQL for CMUCL, which
includes both comprehensive reference documentation and source code
that shows what is and isn't exported.  It also shows that generally
the granularity of packages is larger than the class, and rightly so.

For MaiSQL see http://www.pmsf.de/pmai/MaiSQL.html, for other CL code
see e.g. http://www.alu.org/.

Regs, Pierre.

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
From: Andrew Cooke
Subject: Re: What are some ways of packaging a class and its methods?
Date: 
Message-ID: <88tp9g$mjd$1@nnrp1.deja.com>
In article <·················@poboxes.com>,
  Masoud Pirnazar <··········@poboxes.com> wrote:
> >Define a package and export your functions and methods
> >that define the protocol for the class.
> >Maybe also the class name.
> This is what I was asking:  what has to be exported.
[...]

[I can't find the original message]

When I first wrote something with CLOS I stuck each class in a package,
because it seemed like the only way to really hide data.  But even then,
people can access it.  So I gave up - Lisp doesn't enforce hiding data
and packages seem to be for wrapping up bigger things than single
classes.

Sorry if this is irrelevant - as I said, I can't find the original post.

Andrew
http://www.andrewcooke.free-online.co.uk/index.html

PS.  Use :first and :last instead of 'first and 'last - things beginning
with ":" don't get restricted to packages (I probably haven't phrased
that right, but you know what I mean...)


Sent via Deja.com http://www.deja.com/
Before you buy.
From: Andrew Cooke
Subject: Re: What are some ways of packaging a class and its methods?
Date: 
Message-ID: <88trkv$o1d$1@nnrp1.deja.com>
Continuing at the level of Java-programmer-new-to-Lisp...

Also, because Lisp has so many more ways of doing things, I don't use
classes/CLOS anywhere near as much.  For example, when in Java I would
use a small class to hide a counter, I would use a closure in Lisp
(write a function that returns a counter function from within a lexical
scope that contains the counter itself - there may be other ways).

Andrew
http://www.andrewcooke.free-online.co.uk/index.html

In article <············@nnrp1.deja.com>,
  Andrew Cooke <······@andrewcooke.free-online.co.uk> wrote:
> When I first wrote something with CLOS I stuck each class in a
package,
> because it seemed like the only way to really hide data.  But even
then,
> people can access it.  So I gave up - Lisp doesn't enforce hiding data
> and packages seem to be for wrapping up bigger things than single
> classes.


Sent via Deja.com http://www.deja.com/
Before you buy.
From: Robert Monfera
Subject: Re: What are some ways of packaging a class and its methods?
Date: 
Message-ID: <38B2BBC5.66941F89@fisec.com>
Andrew Cooke wrote:

> Lisp doesn't enforce hiding data
> and packages seem to be for wrapping up bigger things than single
> classes.

Yes, packages never meant to hide things in the C++ sense.  It is not
difficult to hide if you really need to, for example with closures or
the MOP.  (Of course, sufficiently smart debuggers will always allow you
to take a peek and circumvent these measures both in Lisp and C++,
unless you use encryption.)  Yet you can't hide methods _in conjunction
with_ classes without making a conceptual error.

Robert
From: Marco Antoniotti
Subject: Re: What are some ways of packaging a class and its methods?
Date: 
Message-ID: <lwbt5962px.fsf@parades.rm.cnr.it>
Masoud Pirnazar <··········@poboxes.com> writes:

> >Define a package and export your functions and methods
> >that define the protocol for the class.
> >Maybe also the class name.
> This is what I was asking:  what has to be exported.
> 
> 1.  Some of the methods use symbols such as 'first and 'last.  I can export
> these, but they may pollute the importer's namespace (i.e. if the importing
> package already has a 'first).  Instead, I can use :first and :last, or
> require the caller to use 'cons2:first.

The second you wrote :) (Ok, this is an inner joke for the Italian
crowd).
Anyway.  That's what I would do. I.e., if I must have names in my
special package which conflict with names in other packages, then I 'd
shadow those and warn against USE-PACKAGE my package.  There is
nothing wrong with this.

> 2. class definitions create additional symbols (e.g. slot names).  Some
> implementations (I think cmucl) disallow keywords for slot names.  If others
> have actually created classes within packages, they would have run into these
> issues, and have some standard solutions for them.
> 
> I'm looking for some example packaged modules to use as paradigms when
> creating new modules.

Check out the QUEUES package (a shameless plug :) ) in the CLOCC
(http://www.sourceforge.net).

Cheers

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - 06 68 10 03 17, fax. +39 - 06 68 80 79 26
http://www.parades.rm.cnr.it/~marcoxa