[comp.lang.clos] clos and packages

brand@ils.nwu.edu (Matthew Brand) (12/11/90)

	Evidently in Common Lisp, CLOS and packages don't get along
	very well.  Specifically, it's impossible to export a method
	from two packages and then use them without producing a name 
	clash.  

	For example, let's say I have a spline package and a fractal
	package, both defining the method "show".  E.g.:

;;; FILE "spline.lisp"			;;; FILE "fractal.lisp"
(provide 'spline-utilities)		(provide 'fractal-utilities)
(in-package 'spline-package)		(in-package 'fractal-package)
(export '(show))			(export '(show))
(defmethod show ((s spline)) .... )	(defmethod show ((s fractal)) .... )

	;;; transcript
	> (load "spline-utilities")
	#P"/homes/brand/work/spline-utilities"
	> (load "fractal-utilities")
	#P"/homes/brand/work/fractal-utilities"
	> (use-package 'spline-package)
	T
	> (use-package 'fractal-package)
	>>Error: If the USER package were to 'use' the FRACTAL-PACKAGE package,
             there would be name conflicts with symbols found in the 
             following packages ("SPLINE-PACKAGE" "FRACTAL-PACKAGE")
             The particular symbols involved are:
             (SHOW)

	Now if I have to have a different name for the method of each
	package, that rather defeats the point of using an object system.
	On the other hand, since CLOS doesn't allow me to make functions
	private or public, I need to use packages.  Whoever wrote the intern
	function forgot to check whether or not a symbol references a method;
	in that case interning should proceed, provided that the argument
	lists are congruent.  Hence my question:

	Does anybody have a fix for this?

	Also, does this only happen in Lucid CommonLisp with PCL?

	help much appreciated,
	matt brand

barmar@think.com (Barry Margolin) (12/11/90)

In article <183@anaxagoras.ils.nwu.edu> brand@ils.nwu.edu (Matthew Brand) writes:
>	Now if I have to have a different name for the method of each
>	package, that rather defeats the point of using an object system.

If the two classes are implementing methods for the same generic function,
then they should both reference the same generic function name, not symbols
in different packages.

>	On the other hand, since CLOS doesn't allow me to make functions
>	private or public, I need to use packages.  Whoever wrote the intern
>	function forgot to check whether or not a symbol references a method;
>	in that case interning should proceed, provided that the argument
>	lists are congruent.  Hence my question:

The identity of symbols in Common Lisp is independent of what they happen
to be used to name at any particular time.  A symbol may simultaneously
name a global variable, a function (either generic or not), a property
list, a slot (of both a defstruct and a class), a property on a property
list, an entry in an alist, an entry in a hash table, etc.

>	> (use-package 'spline-package)
>	T
>	> (use-package 'fractal-package)
>	>>Error: If the USER package were to 'use' the FRACTAL-PACKAGE package,
>             there would be name conflicts with symbols found in the 
>             following packages ("SPLINE-PACKAGE" "FRACTAL-PACKAGE")
>             The particular symbols involved are:
>             (SHOW)

You complain above about INTERN, but your example uses EXPORT and
USE-PACKAGE, which are completely different.  Symbols have identity
independent of their names; they are first-class Lisp objects, and other
objects have references to them.  However, a package can only have one
symbol with a particular name.  The entry for "SHOW" in the using package
can either be refer to SPLINE-PACKAGE:SHOW or FRACTAL-PACKAGE:SHOW, but it
can't refer to both.  You can't just get rid of one of them, because there
are all these references to them.

>	Does anybody have a fix for this?

Create a new package, e.g. GEOMETRY-PACKAGE, which will be used for symbols
common to splines, fractals, etc.  Export these symbols from
GEOMETRY-PACKAGE, and have SPLINE-PACKAGE and FRACTAL-PACKAGE do
(use-package 'geometry-package).

>	Also, does this only happen in Lucid CommonLisp with PCL?

It's normal Common Lisp.  Symbols are just symbols.

There was a discussion in comp.lang.lisp a couple of months ago about
whether packages are appropriate for emulating the public/private
mechanisms of some other object systems, and whether one package per class
is reasonable.  The concensus is that the package system was designed for
a small number of large groups, not lots of tiny packages.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

jwz@lucid.com (Jamie Zawinski) (12/11/90)

In article <183@anaxagoras.ils.nwu.edu> brand@ils.nwu.edu (Matthew Brand) wrote:
> 
> 	Evidently in Common Lisp, CLOS and packages don't get along
> 	very well.  Specifically, it's impossible to export a method
> 	from two packages and then use them without producing a name 
> 	clash.  

You can accomplish this by setting up the package state the way you want it
beforehand; something like (using your example):

	(make-package "SPLINE")
	(make-package "FRACTAL")
	(export 'spline::show "SPLINE")
	(import 'spline:show "FRACTAL")

;; ... then you load your programs, effectively doing

	(in-package "SPLINE")
	(export 'show)  		; this is the symbol SPLINE:SHOW
	(in-package "FRACTAL")
	(export 'show)			; this also is SPLINE:SHOW

	(in-package "MYPACK" :use '("LISP" "SPLINE" "FRACTAL"))
	'show				; no conflict.

Given the way the package system interacts with the reader, it's not unusual
to have to tailor the package state before loading anything; in fact, doing so
can save you lots of pain and agony even if it's not strictly necessary.

> Whoever wrote the intern function forgot to check whether or not a symbol
> references a method; in that case interning should proceed, provided that 
> the argument lists are congruent.

The behaviour of INTERN has nothing to do with whether a symbol has a function
or method definition; it operates only on symbols and package hierarchies.
Lisp's namespaces are tied to symbols inseperably, so it's not possible to
import a variable FOO without also importing some hypothetical function FOO 
as well.
		-- Jamie

jonl@LUCID.COM (Jon L White) (12/11/90)

re: The concensus is that the package system was designed for
    a small number of large groups, not lots of tiny packages.

I would question the wisdom of this "consensus".  I recall the design
goal of the package system as: it is for a parse-time separation of
identifiers into separate packages rather than for a semantic-analysis-
time separation of object/function/type/etc names.

Given that goal (rather than the one of being only for "large groups"),
it becomes a somewhat interesting question as to whether such-and-such
an application in a more "conventional" computer language (such as ADA?
or MODULA?) should avail itself of lisp packages when being translated
or emulated into Common Lisp.  I can certainly forsee cases where it
is easier and more natural to "put every class into its own package",
even though that would force an inordinate amount (from the Lisp point
of view) of EXPORTing and IMPORTing.


Sigh, I can see that a substantial portion of the traffic on this
discussion list (comp.lang.lisp) will be in exploring and defending
agains the "other" kind of notions for "encapsulation".


-- JonL --