From: rif
Subject: packages, compilation, and eval-when
Date: 
Message-ID: <wj0d6errv3v.fsf@five-percent-nation.mit.edu>
I'm having a ton of trouble figuring out interactions between
packages, compilation, and eval-when.

The specific situation is that I'm using matlisp
(http://matlisp.sourceforge.net).  I want to load the matlisp package,
unexport a symbol (REAL) from matlisp (because it conflicts with a
symbol in :common-lisp).  I also want to define a new package that
uses matlisp (I call it matlisp-utilities).  I would like to do all
this in a file that gets compiled and loaded.  My current (not quite
working) attempt is:

(eval-when (:compile-toplevel :load-toplevel :execute)
  (unless (find-package 'matlisp)
    (format t "~%Loading matlisp.")
    (load "/home/rif/Software/matlisp/start.lisp")))

(eval-when (:compile-toplevel :load-toplevel :execute)
  (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
    (declare (ignore name))
    (when (eq type :external)
      (format t "~%Unexporting 'REAL' from 'matlisp.")
      (unexport 'matlisp::real 'matlisp))))

(defpackage "MATLISP-UTILITIES"
  (:use :common-lisp :matlisp)
  (:export "1D-ARRAY-TO-COL" "1D-ARRAY-TO-ROW" "1D-ARRAY-TO-MATRIX" "MATRIX-SQRT!" "ROW-SUM"))

This works fine if I'm compiling, but if I start a new CL image (I'm
using CMUCL 18e if that's relevant) and try to load the compiled code,
it complains that the package MATLISP does not exist.

I've been digging through the sections on compilation and eval-when in
the hyperspec, but I just can't seem to get it.  

Some more specific questions that may relate to my confusion:

1. From the glossry, it seems that "compile-time" is when CL is
turning my file into compiled code (in CMUCL, going from the .lisp to
the .x86f file), and "load-time" is when I'm loading the .x86f file
(or the .lisp file, or is load-time only when I'm loading *compiled*
code???)  Is this essentially correct?

2. Is there a close connection between "load-time" and the
:load-toplevel keyword to eval-when, or are these two different
things?  From the table in Section 3.2.3.1, it seems that maybe
:load-toplevel form only effects what happens at compile time --- LT
specified just seems to indicate that the forms will be processed as
top level forms.

3.  What is the difference, semantically, between

(eval-when (:compile-toplevel :load-toplevel :execute)
  (unless (find-package 'matlisp)
    (format t "~%Loading matlisp.")
    (load "/home/rif/Software/matlisp/start.lisp")))

(eval-when (:compile-toplevel :load-toplevel :execute)
  (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
    (declare (ignore name))
    (when (eq type :external)
      (format t "~%Unexporting 'REAL' from 'matlisp.")
      (unexport 'matlisp::real 'matlisp))))

and

(eval-when (:compile-toplevel :load-toplevel :execute)
  (unless (find-package 'matlisp)
    (format t "~%Loading matlisp.")
    (load "/home/rif/Software/matlisp/start.lisp")
    (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
      (declare (ignore name))
      (when (eq type :external)
        (format t "~%Unexporting 'REAL' from 'matlisp.")
        (unexport 'matlisp::real 'matlisp)))))

?  The latter doesn't seem to work at all, even when compiling the
file, but I'm unclear why.

I'm pretty lost here, so any help anyone can offer will be most appreciated.

Thanks,

rif

From: Barry Margolin
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <B663b.446$mD.231@news.level3.com>
In article <···············@five-percent-nation.mit.edu>,
rif  <···@mit.edu> wrote:
>(eval-when (:compile-toplevel :load-toplevel :execute)
>  (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
>    (declare (ignore name))
>    (when (eq type :external)
>      (format t "~%Unexporting 'REAL' from 'matlisp.")
>      (unexport 'matlisp::real 'matlisp))))

Get rid of the IGNORE declaration and change the last line to:

       (unexport name 'matlisp)

-- 
Barry Margolin, ··············@level3.com
Level(3), 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: rif
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <wj0oey94x9o.fsf@five-percent-nation.mit.edu>
(Removing format statements for brevity)

I now understand why 

(eval-when (:compile-toplevel :load-toplevel :execute)
  (unless (find-package 'matlisp)
    (load "/home/rif/Software/matlisp/start.lisp")
    (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
      (when (eq type :external)
        (unexport 'matlisp::real 'matlisp))))

gives an error, but replacing 'matlisp::real with name works.  I still
don't understand why

(eval-when (:compile-toplevel :load-toplevel :execute)
  (unless (find-package 'matlisp)
    (load "/home/rif/Software/matlisp/start.lisp")))

(eval-when (:compile-toplevel :load-toplevel :execute)
  (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
    (when (eq type :external)
      (unexport 'matlisp::real 'matlisp))))

works OK if I'm compiling the file, but not if I try to reload the
compiled file in a new image.  By the time the second form is read,
won't the first form have been evaluated, bringing the package MATLISP
into existance?

Cheers,

rif
From: Barry Margolin
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <LYq3b.471$mD.390@news.level3.com>
In article <···············@five-percent-nation.mit.edu>,
rif  <···@mit.edu> wrote:
>
>(Removing format statements for brevity)
>
>I now understand why 
>
>(eval-when (:compile-toplevel :load-toplevel :execute)
>  (unless (find-package 'matlisp)
>    (load "/home/rif/Software/matlisp/start.lisp")
>    (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
>      (when (eq type :external)
>        (unexport 'matlisp::real 'matlisp))))
>
>gives an error, but replacing 'matlisp::real with name works.  I still
>don't understand why
>
>(eval-when (:compile-toplevel :load-toplevel :execute)
>  (unless (find-package 'matlisp)
>    (load "/home/rif/Software/matlisp/start.lisp")))
>
>(eval-when (:compile-toplevel :load-toplevel :execute)
>  (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
>    (when (eq type :external)
>      (unexport 'matlisp::real 'matlisp))))
>
>works OK if I'm compiling the file, but not if I try to reload the
>compiled file in a new image.  By the time the second form is read,
>won't the first form have been evaluated, bringing the package MATLISP
>into existance?

When you load a compiled file, there's no "reading" going on.  All the
reading took place at compile time.

-- 
Barry Margolin, ··············@level3.com
Level(3), 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: rif
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <wj065khr6nl.fsf@five-percent-nation.mit.edu>
Barry Margolin <··············@level3.com> writes:

> In article <···············@five-percent-nation.mit.edu>,
> rif  <···@mit.edu> wrote:
> >
> >(Removing format statements for brevity)
> >
> >I now understand why 
> >
> >(eval-when (:compile-toplevel :load-toplevel :execute)
> >  (unless (find-package 'matlisp)
> >    (load "/home/rif/Software/matlisp/start.lisp")
> >    (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
> >      (when (eq type :external)
> >        (unexport 'matlisp::real 'matlisp))))
> >
> >gives an error, but replacing 'matlisp::real with name works.  I still
> >don't understand why
> >
> >(eval-when (:compile-toplevel :load-toplevel :execute)
> >  (unless (find-package 'matlisp)
> >    (load "/home/rif/Software/matlisp/start.lisp")))
> >
> >(eval-when (:compile-toplevel :load-toplevel :execute)
> >  (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
> >    (when (eq type :external)
> >      (unexport 'matlisp::real 'matlisp))))
> >
> >works OK if I'm compiling the file, but not if I try to reload the
> >compiled file in a new image.  By the time the second form is read,
> >won't the first form have been evaluated, bringing the package MATLISP
> >into existance?
> 
> When you load a compiled file, there's no "reading" going on.  All the
> reading took place at compile time.

I still don't quite get it.  As I currently understand, at
compile-time, the first form is read and compiled, then the second
form is read and compiled --- because the compilation of the first
form brings the MATLISP package into existance, the second form can be
read and compiled without error.  What actually happens when I load
the compiled file that causes things to break?  

rif
From: Barry Margolin
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <9gs3b.481$mD.179@news.level3.com>
In article <···············@five-percent-nation.mit.edu>,
rif  <···@mit.edu> wrote:
>
>Barry Margolin <··············@level3.com> writes:
>
>> In article <···············@five-percent-nation.mit.edu>,
>> rif  <···@mit.edu> wrote:
>> >
>> >(Removing format statements for brevity)
>> >
>> >I now understand why 
>> >
>> >(eval-when (:compile-toplevel :load-toplevel :execute)
>> >  (unless (find-package 'matlisp)
>> >    (load "/home/rif/Software/matlisp/start.lisp")
>> >    (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
>> >      (when (eq type :external)
>> >        (unexport 'matlisp::real 'matlisp))))
>> >
>> >gives an error, but replacing 'matlisp::real with name works.  I still
>> >don't understand why
>> >
>> >(eval-when (:compile-toplevel :load-toplevel :execute)
>> >  (unless (find-package 'matlisp)
>> >    (load "/home/rif/Software/matlisp/start.lisp")))
>> >
>> >(eval-when (:compile-toplevel :load-toplevel :execute)
>> >  (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
>> >    (when (eq type :external)
>> >      (unexport 'matlisp::real 'matlisp))))
>> >
>> >works OK if I'm compiling the file, but not if I try to reload the
>> >compiled file in a new image.  By the time the second form is read,
>> >won't the first form have been evaluated, bringing the package MATLISP
>> >into existance?
>> 
>> When you load a compiled file, there's no "reading" going on.  All the
>> reading took place at compile time.
>
>I still don't quite get it.  As I currently understand, at
>compile-time, the first form is read and compiled, then the second
>form is read and compiled --- because the compilation of the first
>form brings the MATLISP package into existance, the second form can be
>read and compiled without error.  What actually happens when I load
>the compiled file that causes things to break?  

The details depend on the implementation, but here's a simplified account
of how things may work.  Often, one of the first things in a compiled file
is some kind of symbol table, listing all the symbols that are referenced
in it.  The compiled code contains placeholders that are replaced with
pointers to the actual symbol in the image.

What this basically means is that the first thing that happens when you
load a compiled file is that it needs to intern *all* the symbols that are
referenced anywhere in it.  This is not too different from what a link
editor for a more conventional programming language does.

-- 
Barry Margolin, ··············@level3.com
Level(3), 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: rif
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <wj0isohsik5.fsf@five-percent-nation.mit.edu>
> >I still don't quite get it.  As I currently understand, at
> >compile-time, the first form is read and compiled, then the second
> >form is read and compiled --- because the compilation of the first
> >form brings the MATLISP package into existance, the second form can be
> >read and compiled without error.  What actually happens when I load
> >the compiled file that causes things to break?  
> 
> The details depend on the implementation, but here's a simplified account
> of how things may work.  Often, one of the first things in a compiled file
> is some kind of symbol table, listing all the symbols that are referenced
> in it.  The compiled code contains placeholders that are replaced with
> pointers to the actual symbol in the image.
> 
> What this basically means is that the first thing that happens when you
> load a compiled file is that it needs to intern *all* the symbols that are
> referenced anywhere in it.  This is not too different from what a link
> editor for a more conventional programming language does.
> 

Ah, lightbulb.  Thanks for being so patient.  So in some sense, the
"order" of the forms in the original source file is not the whole
story once we've compiled.  The :load-toplevel is doing what I want,
which is causing the form to be evaluated at load-time, but I'm losing
because the symbol matlisp::real needs to be interned before the
matlisp file gets loaded by the "first" form.  I presume there's some
magic associated with defpackage so that the package gets defined
first before the symbols inside it need to be interned?

Is there any good documentation that explains this stuff?  I'd been
reading the hyperspec, but I certainly didn't find anything that
helped as much as the explanation you just gave.

Again, thanks much.

Cheers,

rif
From: Barry Margolin
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <Zpt3b.482$mD.367@news.level3.com>
In article <···············@five-percent-nation.mit.edu>,
rif  <···@mit.edu> wrote:
>Ah, lightbulb.  Thanks for being so patient.  So in some sense, the
>"order" of the forms in the original source file is not the whole
>story once we've compiled.  The :load-toplevel is doing what I want,
>which is causing the form to be evaluated at load-time, but I'm losing
>because the symbol matlisp::real needs to be interned before the
>matlisp file gets loaded by the "first" form.  I presume there's some
>magic associated with defpackage so that the package gets defined
>first before the symbols inside it need to be interned?

The expansion of DEFPACKAGE most likely contain strings, not symbols.  Use
MACROEXPAND to see this.

>Is there any good documentation that explains this stuff?  I'd been
>reading the hyperspec, but I certainly didn't find anything that
>helped as much as the explanation you just gave.

I doubt it's documented well anywhere.  It's the kind of thing you figure
out like this.

-- 
Barry Margolin, ··············@level3.com
Level(3), 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: Pascal Bourguignon
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <87vfsj6oh9.fsf@thalassa.informatimago.com>
rif <···@mit.edu> writes:
> 
> (eval-when (:compile-toplevel :load-toplevel :execute)
>   (unless (find-package 'matlisp)
>     (format t "~%Loading matlisp.")
>     (load "/home/rif/Software/matlisp/start.lisp")
>     (multiple-value-bind (name type) (find-symbol "REAL" 'matlisp)
>       (declare (ignore name))
>       (when (eq type :external)
>         (format t "~%Unexporting 'REAL' from 'matlisp.")
>         (unexport 'matlisp::real 'matlisp)))))
> 
> ?  The latter doesn't seem to work at all, even when compiling the
> file, but I'm unclear why.
> 
> I'm pretty lost here, so any help anyone can offer will be most appreciated.
> 
> Thanks,

That's because  the "packages are  not dynamic".  That is,  the symbol
matlisp::real  which belongs to  the package  matlisp is  created even
before  compile time,  load  time or  run  time: it's  created by  the
reader!  Since there is no package  named matlisp where to put it, the
reader is at loss.

However, the reader reads and evaluate one (top-level) sexp at a time,
so when  you split this expression  in two, the loaded  file will have
created the package before the reader tries to attach matlisp::real to
the package.



That's the reason why it's often advised to define all the packages in
one file to be  loaded once for all at the beginning,  so this kind of
problems  diseappears (but  I don't  like this  solution, I'm  used to
MODULA-2 where  the notion of  package (called MODULE in  MODULA-2) is
much cleaner (but then, it's not such a dynamic language as Lisp)).

-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
From: Matthew Danish
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <20030827180854.GJ1454@mapcar.org>
On Wed, Aug 27, 2003 at 06:42:58PM +0200, Pascal Bourguignon wrote:
> (but  I don't  like this  solution, I'm  used to MODULA-2 where  the
> notion of  package (called MODULE in  MODULA-2) is much cleaner (but
> then, it's not such a dynamic language as Lisp)).

Lisp packages are not "modules".  They solve a different problem.

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
From: Pascal Bourguignon
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <874r01bltm.fsf@thalassa.informatimago.com>
Matthew Danish <·······@andrew.cmu.edu> writes:

> On Wed, Aug 27, 2003 at 06:42:58PM +0200, Pascal Bourguignon wrote:
> > (but  I don't  like this  solution, I'm  used to MODULA-2 where  the
> > notion of  package (called MODULE in  MODULA-2) is much cleaner (but
> > then, it's not such a dynamic language as Lisp)).
> 
> Lisp packages are not "modules".  They solve a different problem.

Well, I'm at loss here. What  are the differences in the problems they
solve?

-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
From: Barry Margolin
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <5st3b.483$mD.481@news.level3.com>
In article <··············@thalassa.informatimago.com>,
Pascal Bourguignon  <····@thalassa.informatimago.com> wrote:
>Matthew Danish <·······@andrew.cmu.edu> writes:
>
>> On Wed, Aug 27, 2003 at 06:42:58PM +0200, Pascal Bourguignon wrote:
>> > (but  I don't  like this  solution, I'm  used to MODULA-2 where  the
>> > notion of  package (called MODULE in  MODULA-2) is much cleaner (but
>> > then, it's not such a dynamic language as Lisp)).
>> 
>> Lisp packages are not "modules".  They solve a different problem.
>
>Well, I'm at loss here. What  are the differences in the problems they
>solve?

Module systems typically distinguish the way names are used.  You export
functions, variables, classes, etc., not symbols.  The Lisp package system
deals only with the names; the attributes come along for the ride.

But most other languages don't have symbols as first-class objects, so they
don't have to deal with the distinction.

-- 
Barry Margolin, ··············@level3.com
Level(3), 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: Pascal Bourguignon
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <87lltd9ttc.fsf@thalassa.informatimago.com>
Barry Margolin <··············@level3.com> writes:

> In article <··············@thalassa.informatimago.com>,
> Pascal Bourguignon  <····@thalassa.informatimago.com> wrote:
> >Matthew Danish <·······@andrew.cmu.edu> writes:
> >
> >> On Wed, Aug 27, 2003 at 06:42:58PM +0200, Pascal Bourguignon wrote:
> >> > (but  I don't  like this  solution, I'm  used to MODULA-2 where  the
> >> > notion of  package (called MODULE in  MODULA-2) is much cleaner (but
> >> > then, it's not such a dynamic language as Lisp)).
> >> 
> >> Lisp packages are not "modules".  They solve a different problem.
> >
> >Well, I'm at loss here. What  are the differences in the problems they
> >solve?
> 
> Module systems typically distinguish the way names are used.  You export
> functions, variables, classes, etc., not symbols.  The Lisp package system
> deals only with the names; the attributes come along for the ride.
> 
> But most other languages don't have symbols as first-class objects, so they
> don't have to deal with the distinction.

I find  this distinction  insubstancial.  Of course,  in Lisp  we (the
programmers) deal  with the  symbols while in  the other  langues, the
symbols are dealt with for us by the compiler and linker.

But when you're dealing with  overall stuff such as package, you don't
get much  mixed up with  such details  as whether x  is a symbol  or a
name.  What  you want is to  separate name spaces,  to avoid conflicts
and allow several  programmers to work on separate  modules.  What you
want here is to be able  to load whatever package you fetched from the
Internet and have a clearly documented interface to it, and be able to
use  it  along  with  thousands  of  other  packages  bought,  locally
developed or fetched from the Internet.

Note that  whatever you're saying  about the lispy symbols  dealt with
packages, they don't allow you to import one slot from one package and
to import another slot from another.  In effect, it works exactly like
in Modula-2 in this respect.   Actually with the ability to import and
re-export symbols, I should say that Lisp is closer to Modula-3.



Starting /usr/local/bin/clisp -ansi -q -K full -m 32MB -I ...
;; Loading file /home/pascal/.clisprc.lisp ...
;; Loaded file /home/pascal/.clisprc.lisp
[1]> 
[2]> (defpackage "A" (:export "X"))
#<PACKAGE A>
[9]> (in-package "A")
#<PACKAGE A>
A[10]> (defvar x 'a-variable)
X
A[11]> (in-package "COMMON-LISP-USER")
#<PACKAGE COMMON-LISP-USER>
[12]> (defpackage "B" (:export "X"))
#<PACKAGE B>
[13]> (in-package "B")
#<PACKAGE B>
B[14]> (defun x () 'a-function)
X
B[15]> (in-package "COMMON-LISP-USER")
#<PACKAGE COMMON-LISP-USER>
[16]> (use-package "A")
T
[17]> x
A::A-VARIABLE
[18]> (use-package "B")
** - Continuable Error
1 name conflicts while executing USE-PACKAGE of (#<PACKAGE B>) into package #<PACKAGE COMMON-LISP-USER>.
If you continue (by typing 'continue'): You may choose for every conflict in favour of which symbol to resolve it.
1. Break [19]> continue
which symbol with name "X" should be accessible in #<PACKAGE COMMON-LISP-USER> ?
Please choose:
          1  --  B
          2  --  COMMON-LISP-USER

>> 1

T
[20]> x
*** - EVAL: variable X has no value
1. Break [21]> 
[22]> (x)
B::A-FUNCTION
[23]> 


-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
From: Thomas A. Russ
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <ymid6eokzkl.fsf@sevak.isi.edu>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> 
> Barry Margolin <··············@level3.com> writes:
> 
> > Module systems typically distinguish the way names are used.  You export
> > functions, variables, classes, etc., not symbols.  The Lisp package system
> > deals only with the names; the attributes come along for the ride.
> > 
> > But most other languages don't have symbols as first-class objects, so they
> > don't have to deal with the distinction.
> 
> I find  this distinction  insubstancial.  Of course,  in Lisp  we (the
> programmers) deal  with the  symbols while in  the other  langues, the
> symbols are dealt with for us by the compiler and linker.
> 
> But when you're dealing with  overall stuff such as package, you don't
> get much  mixed up with  such details  as whether x  is a symbol  or a
> name.  What  you want is to  separate name spaces,

But packages only deal with the mapping of names to symbols.  That is
all that they deal with in Common Lisp.  Packages are only for managing
the mapping between symbol names and symbol objects.

You do get separate namespaces for symbols.  You only get into trouble
when you try to import separate symbols the same symbol-name from
multiple packages.

Packages are really only about this name mapping.  Thinking or wishing
that they perform another function for you as well will not lead to
productive Lisp work.

>  to avoid conflicts
> and allow several  programmers to work on separate  modules.  What you
> want here is to be able  to load whatever package you fetched from the
> Internet and have a clearly documented interface to it, and be able to
> use  it  along  with  thousands  of  other  packages  bought,  locally
> developed or fetched from the Internet.

You can do this.  You just have to do it the Common Lisp way.

For starters, you don't have to USE a package to access the parts that
you want.  From the example below, you can get the variable X from
package A by typing A:X and not have it conflict with the function B:X,
simply by using package prefixes.

USE-PACKAGE is a convenience, but it opens you up to a fair number of
potential conflicts and software engineering problems.  Chief among them
is that if a package you are using decides in the future to export
additional symbols, you will get them as well -- and this can cause
problems with code you have developed because the newly exported symbols
could clash with local symbols of yours.

> Note that  whatever you're saying  about the lispy symbols  dealt with
> packages, they don't allow you to import one slot from one package and
> to import another slot from another.  In effect, it works exactly like
> in Modula-2 in this respect.   Actually with the ability to import and
> re-export symbols, I should say that Lisp is closer to Modula-3.

This is not Modula, it is Common Lisp.  Symbols and symbol-names are all
packages deal with.  They do not deal with slots, functions, variables,
classes, types, etc.  This is the crucial thing that you must learn.

> Starting /usr/local/bin/clisp -ansi -q -K full -m 32MB -I ...
> ;; Loading file /home/pascal/.clisprc.lisp ...
> ;; Loaded file /home/pascal/.clisprc.lisp
> [1]> 
> [2]> (defpackage "A" (:export "X"))
> #<PACKAGE A>
> [9]> (in-package "A")
> #<PACKAGE A>
> A[10]> (defvar x 'a-variable)
> X
> A[11]> (in-package "COMMON-LISP-USER")
> #<PACKAGE COMMON-LISP-USER>
> [12]> (defpackage "B" (:export "X"))
> #<PACKAGE B>
> [13]> (in-package "B")
> #<PACKAGE B>
> B[14]> (defun x () 'a-function)
> X
> B[15]> (in-package "COMMON-LISP-USER")
> #<PACKAGE COMMON-LISP-USER>
> [16]> (use-package "A")
> T
> [17]> x
> A::A-VARIABLE
> [18]> (use-package "B")
> ** - Continuable Error
> 1 name conflicts while executing USE-PACKAGE of (#<PACKAGE B>) into package #<PACKAGE COMMON-LISP-USER>.
> If you continue (by typing 'continue'): You may choose for every conflict in favour of which symbol to resolve it.
> 1. Break [19]> continue
> which symbol with name "X" should be accessible in #<PACKAGE COMMON-LISP-USER> ?
> Please choose:
>           1  --  B
>           2  --  COMMON-LISP-USER
> 
> >> 1
> 
> T
> [20]> x
> *** - EVAL: variable X has no value
> 1. Break [21]> 
> [22]> (x)
> B::A-FUNCTION
> [23]> 

Exactly.  Use-package only imports symbols, nothing else.

You cannot have the unqualified symbol-name "X" refer to more than one
symbol at a time.  If you have symbols named "X" in more than one
package, you will have to choose which one you want to call
"COMMON-LISP-USER::X", since you can't have that name refer to both A:X
and B:X at the same time.

You will have to choose.  Or perhaps better yet, just use
package-qualified names.  Then you could have

a:x     =>   A::A-VARIABLE
(b:x)   =>   B::A-FUNCTION

and not have any conflicts.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: D'gou  via google :-
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <b8ccdc00.0308300849.779f487@posting.google.com>
···@sevak.isi.edu (Thomas A. Russ) wrote in message news:<···············@sevak.isi.edu>...
> But packages only deal with the mapping of names to symbols.  That is
> all that they deal with in Common Lisp.  Packages are only for managing
> the mapping between symbol names and symbol objects.
...
> You cannot have the unqualified symbol-name "X" refer to more than one
> symbol at a time.  If you have symbols named "X" in more than one
> package, you will have to choose which one you want to call
> "COMMON-LISP-USER::X", since you can't have that name refer to both A:X
> and B:X at the same time.
> 
> You will have to choose.  Or perhaps better yet, just use
> package-qualified names.  Then you could have
> 
> a:x     =>   A::A-VARIABLE
> (b:x)   =>   B::A-FUNCTION
> 
> and not have any conflicts.

Perhaps part of the confusion is that the "string" "X" in the program
maps to *one* symbol, but that symbol can have multiple disjoint
meanings. I can assign a value to it and that doesn't interfere with
using it as a function name. It can easily "feel" like the 'variable
called X' and the 'function called X' are completely unrelated when in
fact their relationship is just that they are both accessed from the
same symbol. There really isn't a separate namespace where I can use a
function binding from one package's definition of X and a
variable/special binding from another package's definition of X. In a
sense the names are half-overloaded, the name "space" for functions
and variables is entangled by their association with symbols (lexical
variables don't really make this any better).

This isn't necessarily a hideous bug nor a wonderful feature, but it
can be confusing. ;-)

<D\'gou
From: Matthew Danish
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <20030830175517.GP1454@mapcar.org>
On Sat, Aug 30, 2003 at 09:49:24AM -0700, D'gou  via google :- wrote:
> Perhaps part of the confusion is that the "string" "X" in the program
> maps to *one* symbol, but that symbol can have multiple disjoint
> meanings. I can assign a value to it and that doesn't interfere with
> using it as a function name. It can easily "feel" like the 'variable
> called X' and the 'function called X' are completely unrelated when in
> fact their relationship is just that they are both accessed from the
> same symbol. There really isn't a separate namespace where I can use a
> function binding from one package's definition of X and a
> variable/special binding from another package's definition of X. In a
> sense the names are half-overloaded, the name "space" for functions
> and variables is entangled by their association with symbols (lexical
> variables don't really make this any better).
> 
> This isn't necessarily a hideous bug nor a wonderful feature, but it
> can be confusing. ;-)

(defpackage #:foo (:use #:cl) (:export #:x #:*x*))

(in-package #:foo)

(defparameter *x* 0)
(let ((x 1)) (defun x () x))

In this program, there exists some symbols named by the strings "X" and
"*X*" which are interned into the package named by the string "FOO".
These symbols _denote_ variables and functions.  Particularly in the
case of the lexical variable named by the symbol X, for which there are
no side-effects on the symbol object X itself.  The /symbol/ X is used
as a /name/ for the variable.  Said variable is then bound to some
value.  In the special variable named by the symbol *X*, it does happen
that the SYMBOL-VALUE of the symbol *X* corresponds to the value of the
variable named by the symbol *X* but that is an orthogonal matter.  

The function named by the symbol X is global, and is also accessible
through the SYMBOL-FUNCTION of the symbol X.  So if you (FUNCALL 'X) it
will be able to look-up that function definition.  But if said function
was in an FLET or LABELS then I would have to use (FUNCALL (FUNCTION X))
because the symbol X is the /name/ of that function, and FUNCTION looks
it up by that name (and there is no binding of any symbol object slots
for lexical functions).  I didn't write (FUNCTION "X"), which would look
it up by the string "X", which is incorrect in Lisp.

The key points to remember are:

* Symbols are named by strings.

* Functions and variables are /named by symbols/.

* Variables are then bound to values, and functions to values of
  function type.

* Sometimes, the symbol itself has a slot bound to the same value that
  the variable or function, named by that symbol, is bound to.

* Symbols are interned into packages, meaning that the objects are
  entered into a table from which they may be found again, by
  symbol-name.

* The sole purpose of packages is to allow symbols objects with the same
  name to exist in the same Lisp image, by giving the programmer a
  mechanism by which he may have his program's symbols be separated from
  another programmer's symbols.

  Packages have nothing to do with the variables or functions which are
  named by the symbols in the package.  Packages deal in symbol names
  and symbol objects alone.

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
From: james anderson
Subject: Re: packages, compilation, and eval-when
Date: 
Message-ID: <3F50DE5F.A892F832@setf.de>
it would be less confusing if one recognizes that 'X' does not exist. that is,
to take as an example the phrase "a function binding from one package's
definition of X", there is no such thing as "package Y's definition of X". a
symbol is not a "definition" and there is only "the definition of the symbol
named X in package Y."

i wonder if there is anything which would preclude a reader which maintained
*variable-package* and *operator-package* and interning the respective symbols
in the possibly distinct packages, but, in any case, the programs wouldn't be
common lisp.

...

D'gou via google :- wrote:
> 
> ...
> 
> Perhaps part of the confusion is that the "string" "X" in the program
> maps to *one* symbol, but that symbol can have multiple disjoint
> meanings. I can assign a value to it and that doesn't interfere with
> using it as a function name. It can easily "feel" like the 'variable
> called X' and the 'function called X' are completely unrelated when in
> fact their relationship is just that they are both accessed from the
> same symbol. There really isn't a separate namespace where I can use a
> function binding from one package's definition of X and a
> variable/special binding from another package's definition of X. In a
> sense the names are half-overloaded, the name "space" for functions
> and variables is entangled by their association with symbols (lexical
> variables don't really make this any better).
> 
> This isn't necessarily a hideous bug nor a wonderful feature, but it
> can be confusing. ;-)
> 
> <D\'gou