From: Andreas Peldszus
Subject: Package prefixes and symbol equality
Date: 
Message-ID: <20070507203740.96efa31e.andreas.peldszus@web.de>
Hi!

I have a little bunch of questions regarding symbols and package
prefixes. I hope to find someone so kind as to give me some hints to
what seems to be quite mysterious to me. :) I use Allegro-Lisp 7.0.

Here's the starter: I want one function from one package to return a
list of data to some function in another package.

CL-USER: (make-package :a)
#<The A package>
CL-USER: (make-package :b)
#<The B package>
CL-USER: (in-package :a)
#<The A package>
A: (defun f () '(data list do you not think so ?))
F
A: (f)
(DATA LIST DO YOU NOT THINK SO ?)
A: (in-package :b)
#<The B package>
B: (a::f)
(A::DATA LIST DO A::YOU NOT A::THINK A::SO A::?)

My first question would how to return this list as data not being
prefixed with the package identifer. The way it comes now, it would be
not possible for me to work with it, since inside of package B symbols
do not equal:
B: (equal 'DATA (first (a::f))) NIL

The same thing happens when I store data as a parameter in one package
and try to access it from outside.

B: (in-package :a)
#<The A package>
A: (defparameter *data* '(data list do you not think so ?))
*DATA*
A: *data*
(DATA LIST DO YOU NOT THINK SO ?)
A: (in-package :b)
#<The B package>
B: a::*data*
(A::DATA LIST DO A::YOU NOT A::THINK A::SO A::?)

Question number two concerns that fact, that the symbols 'list', 'do'
and 'not' were not package prefixed. Of cource these are keywords of
the language itself, but shouldn't they also get a prefix because the
list they were in is quoted itself?

Now comes the last and third question. I tried to a find way to remove
the prefixes. This was my idea: Take the symbol name as a string an
build a symbol out of it. Although it feeled like a hack, I was please
to see that it worked.

CL-USER: (make-package :c)
#<The C package>
CL-USER: (in-package :c)
#<The C package>
C: (defun g (l)
     (mapcar #'(lambda (x) (read-from-string (symbol-name x))) l))
G
C: (g (a::f))
(DATA LIST DO YOU NOT THINK SO ?)
C: (g a::*data*)
(DATA LIST DO YOU NOT THINK SO ?)

If the function G in package C now again returns a list of symbols, why
do they not get prefixed if I access this very function from outside?

C(25): (in-package :cl-user)
#<The COMMON-LISP-USER package>
CL-USER(26): (c::g (a::f))
(DATA LIST DO YOU NOT THINK SO ?)
CL-USER(27): (c::g a::*data*)
(DATA LIST DO YOU NOT THINK SO ?)

I would have thought to get something like:
(C::DATA LIST DO C::YOU NOT C::THINK C::SO C::?)


Thanks for your time reading. I hope someone has a hint.
Cheers, Andreas

From: Dan Bensen
Subject: Re: Package prefixes and symbol equality
Date: 
Message-ID: <f1o22e$r8u$1@wildfire.prairienet.org>
Andreas Peldszus wrote:
> Here's the starter: I want one function from one package to return a
> list of data to some function in another package.
> 
> B: (a::f)
> (A::DATA LIST DO A::YOU NOT A::THINK A::SO A::?)
> 
> My first question would how to return this list as data not being
> prefixed with the package identifer. 

Hi Andreas.  The elements of your list are (references to) objects
called "symbols".  A symbol is created automatically inside the current
package when you first refer to it.  The package prefixes are necessary
to disambiguate symbols created in different packages.

 > The way it comes now, it would be
> not possible for me to work with it, since inside of package B symbols
> do not equal:
> B: (equal 'DATA (first (a::f))) NIL

Each symbol has a slot (i.e. "attribute" or "member variable") that
contains a reference to its package.  The package slots of A::DATA and
B::DATA are references to packages A and B respectively.  So clearly
they can't be equal.

> #<The B package>
> B: a::*data*
> (A::DATA LIST DO A::YOU NOT A::THINK A::SO A::?)
> 
> Question number two concerns that fact, that the symbols 'list', 'do'
> and 'not' were not package prefixed. Of cource these are keywords of
> the language itself, but shouldn't they also get a prefix because the
> list they were in is quoted itself?

Symbols called DATA, YOU, THINK, SO, and ? were created in package A
because they didn't exist when you first referred to them in package A.
LIST, DO, and NOT already existed, so new symbols with those names
weren't created.

> Now comes the last and third question. I tried to a find way to remove
> the prefixes. This was my idea: Take the symbol name as a string an
> build a symbol out of it. Although it feeled like a hack, I was please
> to see that it worked.
> 
> CL-USER: (make-package :c)
> #<The C package>
> CL-USER: (in-package :c)
> #<The C package>
> C: (defun g (l)
>      (mapcar #'(lambda (x) (read-from-string (symbol-name x))) l))
> G
> C: (g (a::f))
> (DATA LIST DO YOU NOT THINK SO ?)
> C: (g a::*data*)
> (DATA LIST DO YOU NOT THINK SO ?)
> 
> If the function G in package C now again returns a list of symbols, why
> do they not get prefixed if I access this very function from outside?
> 
> C(25): (in-package :cl-user)
> #<The COMMON-LISP-USER package>
> CL-USER(26): (c::g (a::f))
> (DATA LIST DO YOU NOT THINK SO ?)
> CL-USER(27): (c::g a::*data*)
> (DATA LIST DO YOU NOT THINK SO ?)
> 
> I would have thought to get something like:
> (C::DATA LIST DO C::YOU NOT C::THINK C::SO C::?)

Every time you call C::G in a different package, you're creating a new
set of symbols in the current package if they don't already exist.
None of these symbols contain any of the same data as the symbols
you created in other packages, except of course for the print name.

It would help if you could explain what you're trying to do.  If you
just want to print out the symbol names without the prefixes, you can
use the function SYMBOL-NAME.  Otherwise, you need the prefix to make
sure you know which object you're referencing.

-- 
Dan
www.prairienet.org/~dsb/
From: Pascal Costanza
Subject: Re: Package prefixes and symbol equality
Date: 
Message-ID: <5a9bq0F2nq06aU1@mid.individual.net>
Some general notes about packages:

- Packages don't contain and/or export functions, variables, classes, 
etc. They only contain symbols. You can associate functions, variables, 
classes, etc., with symbols, but that doesn't have anything to do with 
packages.

- There is no such thing as a package prefix. There is a printed 
representation of symbols where a package name _may_ come first, 
followed by a single or a double colon, followed by the symbol name. But 
depending on context, the printed representation may be different. (If 
you're in a package in which a symbol is accessible, this symbol will 
not be printed with a preceding package name.)

A symbol is a member of its home package and may be accessible in other 
packages. A symbol has a name, which is a string that is used for its 
printed presentation. A package also has a name which is also a string, 
and the package name is sometimes also used in conjunction with printing 
symbols. Specifically, symbols don't have "package prefixes." (Some 
symbols don't even exist in any package - they are called uninterned 
symbols.)

Andreas Peldszus wrote:
> Hi!
> 
> I have a little bunch of questions regarding symbols and package
> prefixes. I hope to find someone so kind as to give me some hints to
> what seems to be quite mysterious to me. :) I use Allegro-Lisp 7.0.
> 
> Here's the starter: I want one function from one package to return a
> list of data to some function in another package.
> 
> CL-USER: (make-package :a)
> #<The A package>
> CL-USER: (make-package :b)
> #<The B package>
> CL-USER: (in-package :a)
> #<The A package>
> A: (defun f () '(data list do you not think so ?))
> F
> A: (f)
> (DATA LIST DO YOU NOT THINK SO ?)
> A: (in-package :b)
> #<The B package>
> B: (a::f)
> (A::DATA LIST DO A::YOU NOT A::THINK A::SO A::?)
> 
> My first question would how to return this list as data not being
> prefixed with the package identifer. 

This is the wrong question. The right question is: How do you ensure 
that the symbols returned from this function are always from an 
unambiguous package.

One solution is to use the colon-notation to ensure that all symbols 
returned are indeed from some specific package:

(defun f () '(p1:data p1:list p1:do ...))

Another typical approach is to use keyword symbols. These are symbols 
from a predefined package KEYWORD (as per ANSI CL) which always evaluate 
to themselves and are therefore very straightforward to use in such 
circumstances:

(defun f() '(:data :list :do ...))

> Question number two concerns that fact, that the symbols 'list', 'do'
> and 'not' were not package prefixed. Of cource these are keywords of
> the language itself, but shouldn't they also get a prefix because the
> list they were in is quoted itself?

Your code resides in a package that uses the common-lisp package. Thus, 
these symbols are accessible in that package, and thus they are the 
symbols from common-lisp.

The resolution where a symbol comes from is performed at read time, when 
the code is parsed and turned into s-expressions. Especially, this 
resolution step is completely independent from what you use these 
symbols for and how you use them. So you always have to be explicit, or 
define your packages in such a way that implicit uses "automagically" do 
the right thing. But you as the programmer are responsible here.

> Now comes the last and third question. I tried to a find way to remove
> the prefixes. This was my idea: Take the symbol name as a string an
> build a symbol out of it. Although it feeled like a hack, I was please
> to see that it worked.

...but it is still a hack, nevertheless. You seem to haven't understood 
the package concept yet, and this hack is an inappropriate workaround.

My impression is this:

- You seem to be overengineering your source code. Packages should 
usually be coarse-grained and group large functional subsets of your 
program. If two functions collaborate to process the same set of 
symbols, they very likely belong in the same package. Otherwise, one 
function is part of an API and the other is part of some client code - 
in that case, you should first come up with a better design for the API.

In general, Lisp works better if you use a bottom-up approach. In the 
beginning, just stay in the cl-user package, or maybe some 
general-purpose package that you have configured yourself that has some 
symbols from libraries available that you regularly like to use. Only 
later on, when your program becomes sufficiently large, start to 
separate clusters of functionality into their own packages.

- You should study some tutorial about the package system and probably 
the relevant sections in the HyperSpec and CLtL2. It's really important 
to understand how the package system works (that it is a read-time 
concept, that it groups symbols and nothing else, etc.) before you can 
make effective use of it. If your mental model is that it is a kind of 
module system, similar to module systems that you typically find in 
other languages, then your mental model is very likely to be very wrong.


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: Andreas Thiele
Subject: Re: Package prefixes and symbol equality
Date: 
Message-ID: <f1pf5c$1lv$00$1@news.t-online.com>
"Andreas Peldszus" <················@web.de> schrieb im Newsbeitrag 
·············································@web.de...
> Hi!
>
> I have a little bunch of questions regarding symbols and package
> prefixes. I hope to find someone so kind as to give me some hints to
> what seems to be quite mysterious to me. :)
> ...

Hi Andreas,

I think http://www.flownet.com/ron/packages.pdf is helpful reading on this 
topic.


Andreas
From: Andreas Peldszus
Subject: Re: Package prefixes and symbol equality
Date: 
Message-ID: <20070508210312.b2f97812.andreas.peldszus@web.de>
Thanks,

I am reading it atm and I will give a more detailed description of my problem, if it still exists afterwards. Thanks also to Dan and Pascal for the comments. :)

cheers,
Andreas

On Tue, 8 May 2007 11:16:21 +0200
"Andreas Thiele" <······@nospam.com> wrote:

> Hi Andreas,
> 
> I think http://www.flownet.com/ron/packages.pdf is helpful reading on this 
> topic.
> 
> 
> Andreas