Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

atoms in a list interned when called by another package. why?

9 views
Skip to first unread message

gutzofter

unread,
Jul 17, 2008, 12:42:39 PM7/17/08
to
If I have a function in package kratch:

(defun get-kratch ()
(list 'a))

And, I call this when I'm in another package I will get this:

(KRATCH::A)

Why does 'a intern the atom a?

Rainer Joswig

unread,
Jul 17, 2008, 12:58:01 PM7/17/08
to
In article
<cba5c25c-3290-4cfd...@x35g2000hsb.googlegroups.com>,
gutzofter <gutz...@yahoo.com> wrote:

It's a symbol. The READer does intern symbols. When the form
is read, the symbols are interned in some package. Since
you defined the function while in the package "KRATCH", the
symbol A is in that package. Later when you are in another
package, the printer will also print the package name of A
like in KRATCH::A.

--
http://lispm.dyndns.org/

John Thingstad

unread,
Jul 17, 2008, 1:12:14 PM7/17/08
to

I might add that symbols starting with : like :a are interned in the
keyword package which is visible everywhere.
(eql will work!)

--------------
John Thingstad

Pascal J. Bourguignon

unread,
Jul 17, 2008, 1:45:54 PM7/17/08
to
"John Thingstad" <jpt...@online.no> writes:

This is not correct.

Symbols interned in any package are "visible" everywhere when you write
them fully qualified with double-colon:

ANY-PACKAGE::ANY-SYMBOL


Symbols interned in any package that are exported are "visible"
everywhere when you write them fully qualified with single-colon:

ANY-PACKAGE:ANY-EXPORTED-SYMBOL


KEYWORD is an exception in that the package name is optional in the
fully qualified notation:

KEYWORD:ANY-SYMBOL
KEYWORD::ANY-SYMBOL
:ANY-SYMBOL
::ANY-SYMBOL

is the same keyword.


But symbols interned in any package, including KEYWORD are "visible"
ONLY in the package that import them (or use KEYWORD):


C/USER[114]> (defpackage "P2" (:use "CL" "KEYWORD") (:shadowing-import-from "CL" . #.(let ((l '())) (do-external-symbols (s "CL") (push s l)) l)))
#<PACKAGE P2>
C/USER[115]> (in-package "P2")
#<PACKAGE P2>
C/P2[116]> (eql 'test 'keyword::test)
T
C/P2[117]> (eql 'test ':test)
T
C/P2[118]> (in-package "CL-USER")
#<PACKAGE COMMON-LISP-USER>
C/USER[119]> (defpackage "P3" (:use "CL"))
#<PACKAGE P3>
C/USER[120]> (in-package "P3")
#<PACKAGE P3>
C/P3[121]> (eql 'test 'keyword::test) ; when KEYWORD is not used, the keyword named "TEST" is not "visible" in P3.
NIL
C/P3[122]> (eql 'test ':test) ; but of course, we can access that keyword by qualifying it with KEYWORD: or :
NIL
C/P3[123]>


The symbols interned in the keyword package are visible only where the
keyword package is imported, or when they are qualified, fully with
'KEYWORD::' or shortly with ':'.

Notice that keywords are automatically exported, but only once they're
interned. When you read a new keyword, you cannot use
KEYWORD:NEW-KEYWORD, since NEW-KEYWORD is not interned yet in KEYWORD,
therefore not exported yet:

C/USER[124]> 'keyword:foo

*** - READ from #<INPUT CONCATENATED-STREAM #<INPUT
STRING-INPUT-STREAM> #<IO TERMINAL-STREAM>>: #<PACKAGE KEYWORD>
has no external symbol with name "FOO"


C/USER[126]> '(keyword::bar keyword:bar :bar)
(:BAR :BAR :BAR)


--
__Pascal Bourguignon__ http://www.informatimago.com/

WARNING: This product warps space and time in its vicinity.

Zach Beane

unread,
Jul 17, 2008, 1:57:06 PM7/17/08
to
p...@informatimago.com (Pascal J. Bourguignon) writes:

> KEYWORD is an exception in that the package name is optional in the
> fully qualified notation:
>
> KEYWORD:ANY-SYMBOL
> KEYWORD::ANY-SYMBOL
> :ANY-SYMBOL
> ::ANY-SYMBOL
>
> is the same keyword.

Here's a tangent, which I point out because I only recently learned of
it myself, from 2.3.5:

The valid patterns for tokens are summarized in the next figure.

nnnnn a number
xxxxx a symbol in the current package
:xxxxx a symbol in the the KEYWORD package
ppppp:xxxxx an external symbol in the ppppp package
ppppp::xxxxx a (possibly internal) symbol in the ppppp package
:nnnnn undefined
ppppp:nnnnn undefined
ppppp::nnnnn undefined
::aaaaa undefined
aaaaa: undefined
aaaaa:aaaaa:aaaaa undefined

Figure 2-17. Valid patterns for tokens

That is, the syntax "::ANY-SYMBOL" is undefined, not necessarily a
reference to the keyword :ANY-SYMBOL.

Zach

John Thingstad

unread,
Jul 17, 2008, 2:17:54 PM7/17/08
to
På Thu, 17 Jul 2008 19:45:54 +0200, skrev Pascal J. Bourguignon
<p...@informatimago.com>:

well... yes. I should have added without spesifying the package qualifier.

My point was that:

(defpackage :p1 (:use :cl) (:export :v1)) (in-package :p1)

(defparameter v1 (list 'a 'b 'c))

(defpackage :p2 (:use :cl :p1)) (in-package :p2)

(print (every (lambda (x) (member x v1)) (list 'a 'b 'c))) ; member by
default uses &key (test #'eql)

will print nil. This might suprise some beginners.

Replacing (list 'a 'b 'c) with (list :a :b :c) in both packages will give
the 'expected' result.


I mentioned this because some comments read in other threads leads me to
belive some people don't get the point of the keyword package.

--------------
John Thingstad

Rob Warnock

unread,
Jul 17, 2008, 9:28:53 PM7/17/08
to
Zach Beane <xa...@xach.com> wrote:
+---------------

| p...@informatimago.com (Pascal J. Bourguignon) writes:
| > KEYWORD is an exception in that the package name is optional in the
| > fully qualified notation:
| > KEYWORD:ANY-SYMBOL
| > KEYWORD::ANY-SYMBOL
| > :ANY-SYMBOL
| > ::ANY-SYMBOL
| > is the same keyword.
|
| Here's a tangent, which I point out because I only recently learned of
| it myself, from 2.3.5:
| The valid patterns for tokens are summarized in the next figure. [2-17]
...
| ::aaaaa undefined
...

| That is, the syntax "::ANY-SYMBOL" is undefined,
| not necessarily a reference to the keyword :ANY-SYMBOL.
+---------------

While the CLHS certainly does say that,
CLISP & CMUCL *do* both support that pattern:

cmu> ::foo

:FOO
cmu>

which is fine, since CLHS 2.3.5 item #5 explicitly *permits* this:

5. The consequences are unspecified if any other pattern of
package markers in a token is used. All other uses of package
markers within names of symbols are not defined by this
standard but are reserved for implementation-dependent use.

Similarly, both CLISP & CMUCL reject :::FOO.

cmu> (princ (nth-value 1 (ignore-errors (read-from-string ":::foo"))))
Reader error at 3 on #<String-Input Stream>:
too many colons after #<The KEYWORD package, 0/2 internal,
1795/2187 external> name
#<READER-ERROR {4895FFDD}>
cmu>

I'm guessing that most CLs do the same as CLISP & CMUCL do here.


-Rob

-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

Vassil Nikolov

unread,
Jul 17, 2008, 11:11:39 PM7/17/08
to

On Thu, 17 Jul 2008 20:28:53 -0500, rp...@rpw3.org (Rob Warnock) said:
| ...

| 5. The consequences are unspecified if any other pattern of
| package markers in a token is used. All other uses of package
| markers within names of symbols are not defined by this
| standard but are reserved for implementation-dependent use.

As another example, FOO:(BAR BAZ) read as (FOO:BAR FOO:BAZ) (was
that implemented in Lisp Machine Lisp?).

* * *

For completeness, note the effect of *READ-BASE* and see also about
potential numbers. (My favorite potential numbers are rationals
such as 1+2/3.)

---Vassil.


--
Peius melius est. ---Ricardus Gabriel.

Tim Bradshaw

unread,
Jul 18, 2008, 6:23:09 AM7/18/08
to
On Jul 18, 4:11 am, Vassil Nikolov <vnikolov+use...@pobox.com> wrote:

>   As another example, FOO:(BAR BAZ) read as (FOO:BAR FOO:BAZ) (was
>   that implemented in Lisp Machine Lisp?).

Yes, it was.

Thomas F. Burdick

unread,
Jul 18, 2008, 7:25:30 AM7/18/08
to

And it still works under Allegro CL.

Kaz Kylheku

unread,
Jul 18, 2008, 2:02:31 PM7/18/08
to

Interning is done at read time. It is not a form of evaluation, and so it
is not suppressed by quote. The quote is irrelevant; it is the printed
expression A which causes A to be interned when it is read. This happens
whether or not it is quoted.

All symbols occuring in an expression give rise to interning, the only
exception being symbols prefixed with the notation #: (hash, colon).

If this interning wasn't done, then for instance, this would not work:

(eq 'a 'a) -> T

Symbols can have arbitrary meaning within a Lisp expression. They can refer to
a variable, function, type, class, slot, go tag, catch tag, restart---all kinds
of entities which are built-into the language, plus new ones that the
application designer dreams up.

Consistently interning symbols in forms at read time is critical in ensuring
that symbols work smoothly in all situations.

gutzofter

unread,
Jul 18, 2008, 11:13:01 PM7/18/08
to
It makes good sense. The way I found this out; emitting expanded code
from a macro and checking the expanded code in an if. I couldn't get
it to branch properly of the original symbol. This definitely will go
into my 'lesson learned' category.

Kent M Pitman

unread,
Jul 20, 2008, 2:26:14 PM7/20/08
to
Tim Bradshaw <tfb+g...@tfeb.org> writes:

Except be careful because for Zetalisp packages (or maybe Zetalisp
syntax, I don't recall), it meant to bind *PACKAGE* to that package
and then call read. So SI:(FOO BAR) was what CL would write as
(SI::FOO SI::BAR), but only because the SYSTEM-INTERNALS package
(SI, for short) was Zetalisp style and didn't have the internal/external
distinction.

I don't recall if this was mediated by package or by syntax. That is,
whether you had to be in -*- Mode: LISP; Syntax: Zetalisp -*- to see the
effect or if it was globally that way. The reason I might think it was
globally is that it was a porting barrier as we tried to upgrade code that
had "cheated" and used SI:(progn ...) to Common Lisp syntax that one had
to laboriously go through each symbol and not only mark it but determine if
:: or : was appropriate, or else mark large bodies of code with :: everywhere.

Note also, more to the original issue of ::foo, that there was a big divide
between Genera and the other Lisps about how to handle numbers after colon.
Everyone reading the spec insisted that :3600 (a model number of the Lisp
Machine that appeared on *features* should be a symbol, though on the LispM
it was a number). The problem was that
:(3600)
yielded (3600) but people wanted :3600 to be a symbol. The LispM community
argued it should be a number. The compromise eventually reached was to have
both 3600 and :|3600| on the *features* list so that #+3600 could work and
also code that did either (MEMBER 3600 ...) or (MEMBER :3600 ...)
or (MEMBER :|3600| ...).

Kent M Pitman

unread,
Jul 20, 2008, 2:43:03 PM7/20/08
to
gutzofter <gutz...@yahoo.com> writes:

A lot of people replied, but no one hit the fundamental issues, IMO.
It was touched on obliquely a couple of times, but not head on.

First, Common Lisp semantics is defined on structure, not on text.
So the entire language is defined not on what that notation above does,
but on what the internal structure contains. Definitions are made on
symbols, not text notations. Lists are structures, not text notations.
The above definition, at the semantic level for Lisp, contains:

+------>+-------->+----->+---> NIL
| | | |
v v v v
DEFUN GET-KRATCH NIL +---->+---> NIL
| |
v +------>+---> NIL
LIST | |
v v
QUOTE A

means, where the items like DEFUN are not syntax but pointers to
actual symbols in actual packages. So all resolution of what package
is what has been done after READ, as Rainer Joswig explained.

But the part he didn't go into was the purpose of this. The reason
this matters is so that when you do:

(+ x x)

the semantics are defined on:

+---->+----+----> NIL
| | |
v v |
+ X <--+

That is, the references to the two symbols are object-identical. So CL
wants to behave like all symbols are always existing and just waiting to
be named. The point of first reference always ends up being the place at
which the name comes into existence UNLESS the symbol is exported.

The distinction is like in English when you say:

Throw a ball.

which means "there may be several balls. throw one of them" but "throw
the ball" or "throw ball" means "there is only one ball, throw it".

Likewise, (+ x x) means "call the function named + on the variable
named x and the variable named x." There can only be one x because
there has been a definite reference. Symbols are definite references.

This means that if you are in package FOO and write

(+ x foo::x)

you have still written

+---->+----+----> NIL
| | |
v v |
+ X <--+

and NOT

+---->+----+----> NIL
| | |
v v v
+ X FOO::X

Later, when you go to print such an object, Lisp must unravel a good
way to print the symbol that recovers the semantic meaning of the
symbol in context. So in package "FOO", with "BAR" not sharing the
symbol X, doing:

(defun foo () (print 'x))
(let ((*package* "BAR")) (foo))

will print FOO::X because at runtime the symbol X with package FOO
will be known not to print re-readably with package BAR prevailing.
But doing

(foo)

will print just X, even though it's the same symbol being printed,
because PRINT doesn't recover the syntax you used typing in, it works
out from first principles how to print it.

All of this is in service of the idea that symbols name concepts and
that those concepts are independent of the input notation. The entire
purpose of a symbol is to create that object-identity link between
concepts in different places, and so interning is the primary
job. It's not an auxiliary extra. The printing behavior is, in fact,
the derived concept.

Pascal J. Bourguignon

unread,
Jul 20, 2008, 4:26:12 PM7/20/08
to

Well then, to be precise, perhaps we should write:


+--------------->+----------->+----->+--->CL:NIL
| | | |
v v v v
CL:DEFUN KRATCH::GET-KRATCH CL:NIL +------->+--->CL:NIL
| |
v +---------->+--->CL:NIL
CL:LIST | |
v v
CL:QUOTE KRATCH::A

Which is the structure built when reading
"(defun get-kratch() (list 'a))" with CL:*PACKAGE* bound to the package
named KRATCH.

And the reasons PRINT displays "(KRATCH::A)" are:
- CL:*PACKAGE* is not bound to the package named "KRATCH",
- KRATCH::A is not imported in the package bound to CL:*PACKAGE*,
- KRATCH::A is not exported from the package named "KRATCH" (otherwise
it would be displayed as "KRATCH:A").


--
__Pascal Bourguignon__ http://www.informatimago.com/

Nobody can fix the economy. Nobody can be trusted with their finger
on the button. Nobody's perfect. VOTE FOR NOBODY.

Kent M Pitman

unread,
Jul 20, 2008, 8:56:18 PM7/20/08
to
p...@informatimago.com (Pascal J. Bourguignon) writes:

> Well then, to be precise, perhaps we should write:
>
>
> +--------------->+----------->+----->+--->CL:NIL
> | | | |
> v v v v
> CL:DEFUN KRATCH::GET-KRATCH CL:NIL +------->+--->CL:NIL
> | |
> v +---------->+--->CL:NIL
> CL:LIST | |
> v v
> CL:QUOTE KRATCH::A

Well, if you're really going to do that, you have to write something still
even more elaborate with stuff like this in it just even to represent
the DEFUN part...

|
[Symbol-Pointer]
|
v
Symbol
+---------+----+
| Name | +------> "DEFUN" Package
+---------+----+ +-----------+--+
| Package | +--------------------->| Name | +------------> "COMMON-LISP"
+---------+----+ +-----------+--+
| PList | +-----> properties | Nicknames | +----->+-----> NIL
+---------+----+ +-----------+--+ |
| Value | +-----> value | ... | | v
+---------+----+ "CL"
| Function| +-----> function
+---------+----+

etc. But I was too lazy to really flesh it out. It's all object-oriented.
The particular thing I was trying to avoid was showing the string CL:DEFUN
since one might think it was different than the symbol COMMON-LISP:DEFUN.

> Which is the structure built when reading
> "(defun get-kratch() (list 'a))" with CL:*PACKAGE* bound to the package
> named KRATCH.

Yes, modulo the notion that both your and my versions were abbreviated.
Even the above leaves out detail (and exposes the controversial detail
about whether symbols contain values and functions... the amount of
needless presentational bickering over the presentation of this during
the writing of the spec was enormous).

> And the reasons PRINT displays "(KRATCH::A)" are:
> - CL:*PACKAGE* is not bound to the package named "KRATCH",
> - KRATCH::A is not imported in the package bound to CL:*PACKAGE*,
> - KRATCH::A is not exported from the package named "KRATCH" (otherwise
> it would be displayed as "KRATCH:A").

Right.

Pascal J. Bourguignon

unread,
Jul 21, 2008, 2:35:58 AM7/21/08
to
Kent M Pitman <pit...@nhplace.com> writes:

Not only that, but we usually have (eq 'cl:defun cl-user::defun) etc,
and it's possible to have (null (symbol-package 'some-package:some-symbol))
which are the details I didn't want to enter in and why I stopped
at CL:DEFUN ;-)


--
__Pascal Bourguignon__ http://www.informatimago.com/

"A TRUE Klingon warrior does not comment his code!"

0 new messages