From: ·········@gmail.com
Subject: Cross-package symbol equality
Date: 
Message-ID: <1f993365-80e5-4563-a26b-338340575805@o77g2000hsf.googlegroups.com>
Would some be good enough to provide insight as to why test-eq returns
differently based upon which package it's being called from?  A sample
REPL session below.

First, let me note that the file /tmp/test.lisp contains the cons:

((GENERAL .
   ((1 . 2)
    (3 . 4))))

<snip>

CL-USER> (defpackage test-
pkg
           (:use :common-lisp))
#<PACKAGE "TEST-PKG">
CL-USER> (in-package :test-pkg)
#<PACKAGE "TEST-PKG">
TEST-PKG> (defun test-eq (test-
file)
            (let ((read-
input))
              (with-open-file (s test-
file)
                (setf read-input (read
s)))
              (eq (caar read-input)
'GENERAL)))

TEST-
EQ
TEST-PKG> (test-eq #P"/tmp/test.lisp")
T
TEST-PKG> (in-package :cl-user)
#<PACKAGE "COMMON-LISP-
USER">
CL-USER> (test-pkg::test-eq #P"/tmp/test.lisp")
NIL

</snip>

Thanks very much for your help.

- Joseph Knecht

From: Kent M Pitman
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <u7igg5no9.fsf@nhplace.com>
··········@gmail.com" <·········@gmail.com> writes:

> Would some be good enough to provide insight as to why test-eq returns
> differently based upon which package it's being called from?

Because READ interns symbols in the current package unless they have
package qualifiers.  So if you change the package and then call READ,
you are asking for different symbols.

The symbol TEST-PKG::GENERAL is not the symbol CL-USER::GENERAL.
From: ·········@gmail.com
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <a89b7eb7-7409-4f33-b3eb-dd41ecc821f6@y77g2000hsy.googlegroups.com>
On Mar 6, 1:14 am, Kent M Pitman <······@nhplace.com> wrote:
> Because READ interns symbols in the current package unless they have
> package qualifiers.

Ultimately, this is the piece I was missing.  My expectation would be
that read implicitly interns the objects it reads into the calling
package, as opposed to *package*.

On closer thought, I guess that behavior makes sense.  I do wish this
semantic detail was spelled out more clearly in read's Hyperspec page.

Thanks again.
From: Ron Garret
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <rNOSPAMon-7590F9.01093806032008@news.gha.chartermi.net>
In article 
<····································@y77g2000hsy.googlegroups.com>,
 ··········@gmail.com" <·········@gmail.com> wrote:

> On Mar 6, 1:14 am, Kent M Pitman <······@nhplace.com> wrote:
> > Because READ interns symbols in the current package unless they have
> > package qualifiers.
> 
> Ultimately, this is the piece I was missing.  My expectation would be
> that read implicitly interns the objects it reads into the calling
> package, as opposed to *package*.

There is no such thing as "the calling package."  Packages do what they 
do at read-time, not run-time.  But if you're calling READ directly you 
can always bind *PACKAGE*.

> On closer thought, I guess that behavior makes sense.  I do wish this
> semantic detail was spelled out more clearly in read's Hyperspec page.

Section 2.3.4 seems pretty clear to me:

"When parsing the syntax for a symbol, the Lisp reader looks up the name 
of that symbol in the current package."

which is defined as:

"current package n. (in a dynamic environment) the package that is the 
value of *package* in that environment"

rg
From: Alan Crowe
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <86tzjkufcw.fsf@cawtech.freeserve.co.uk>
··········@gmail.com" <·········@gmail.com> writes:

> On Mar 6, 1:14 am, Kent M Pitman <······@nhplace.com> wrote:
> > Because READ interns symbols in the current package unless they have
> > package qualifiers.
> 
> Ultimately, this is the piece I was missing.  My expectation would be
> that read implicitly interns the objects it reads into the calling
> package, as opposed to *package*.

You could make it work the way that you exected like this:

First a data file, data.lisp

(look in this list perhaps cthulu is sleeping here)

Then a file of code, prog.lisp

(defpackage #:lovecraft
  (:use :cl)
  (:export #:foolish-quest))

(in-package :lovecraft)

(defun foolish-quest (eldritch-runes)
  (typecase eldritch-runes
    (list (if (find 'cthulu eldritch-runes)
              'madness-and-death
              'spared))
    (string  (let ((*package* (symbol-package 'cthulu)))
               (with-open-file (stream eldritch-runes)
                 (if (find 'cthulu (read stream))
                     'unspeakable-horror
                     'lucky-escape))))))

Talking with the REPL

CL-USER> (load "prog.lisp")
CL-USER> (use-package "LOVECRAFT")
CL-USER> (foolish-quest (with-open-file (stream "data.lisp")
                          (read stream)))
=> LOVECRAFT::SPARED

Here we see that the symbol, LOVECRAFT::CTHULU, in the code
was different from the symbol, CL-USER::CTHULU, read from
the file.

But given a filename the code binds *package* to the package
in which the code resides before calling READ, which changes
things:

CL-USER> (foolish-quest "data.lisp")
LOVECRAFT::UNSPEAKABLE-HORROR

As does changing the package in which we are working:

CL-USER> (in-package "LOVECRAFT")
#<The LOVECRAFT package, 13/21 internal, 1/2 external>

LOVECRAFT> (foolish-quest (with-open-file (stream "data.lisp")
                          (read stream)))
MADNESS-AND-DEATH

I'm rather proud of my code, it does what was asked for,
interning symbols into "the calling package". Yet I have two
doubts.

1)Ordinarily one has multiple data sets and multiple
  analysis programs. The identities of the symbols used in
  each data set is tied to the specific data set, perhaps by
  some meta-data mechanism. The code I've sketched works
  very differently. READ is building a data structure in
  which the precise identity of the symbols is determined by
  the happen stance of organisation of the code in one of
  the analysis programs.

2)I've not chosen the obvious symbol names, FOUND and
  ABSENT. It is as though my subconscious were trying to
  send me a message.

> 
> On closer thought, I guess that behavior makes sense.  I do wish this
> semantic detail was spelled out more clearly in read's Hyperspec page.
> 

I think that you are seeing a compromise that originated in
the paper based technologies of the time. The Hyperspec
contains some tutorial material. It is to a degree essential
and yet every piece detracts from the crispness of the
specification.

Today one would write a terse specification with hyper links
to diverse tutorial materials aimed at various audiences and
hyper links to commentry, explaining and clarifying
misunderstandings that have arisen.
 
Alan Crowe
Edinburgh
Scotland
From: vanekl
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <fqo1bn$kvg$1@aioe.org>
·········@gmail.com wrote:
> Would some be good enough to provide insight as to why test-eq returns
> differently based upon which package it's being called from?  A sample
> REPL session below.
> 
> First, let me note that the file /tmp/test.lisp contains the cons:
> 
> ((GENERAL .
>    ((1 . 2)
>     (3 . 4))))
> 
> <snip>
> 
> CL-USER> (defpackage test-
> pkg
>            (:use :common-lisp))
> #<PACKAGE "TEST-PKG">
> CL-USER> (in-package :test-pkg)
> #<PACKAGE "TEST-PKG">
> TEST-PKG> (defun test-eq (test-
> file)
>             (let ((read-
> input))
>               (with-open-file (s test-
> file)
>                 (setf read-input (read
> s)))
>               (eq (caar read-input)
> 'GENERAL)))
> 
> TEST-
> EQ
> TEST-PKG> (test-eq #P"/tmp/test.lisp")
> T
> TEST-PKG> (in-package :cl-user)
> #<PACKAGE "COMMON-LISP-
> USER">
> CL-USER> (test-pkg::test-eq #P"/tmp/test.lisp")
> NIL
> 
> </snip>
> 
> Thanks very much for your help.
> 
> - Joseph Knecht

Symbols are interned into packages.
This is one way to get around the problem:

((TEST-PKG::GENERAL .
    ((1 . 2)
     (3 . 4))))

(defun test-eq (test-file)
   (let ((read-input))
     (with-open-file (s test-file)
       (setf read-input (read s)))
     (eq (caar read-input)
	'TEST-PKG::GENERAL)))
From: ·········@gmail.com
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <c1095c5d-1310-4f3c-aad2-62b7736bd62a@q78g2000hsh.googlegroups.com>
On Mar 6, 12:01 am, vanekl <·····@acd.net> wrote:
> Symbols are interned into packages.
> This is one way to get around the problem:

Thanks very much for the quick reply!

Okay, this is fair enough, so by the same token, specifying all
symbols as keywords both in the file and in test-eq (that is,
as :GENERAL) will work as well.

I just assumed that the reader would implicitly intern any symbols
into the package in which the call to read occurred, which clearly
isn't the case.  I remain quite fuzzy as to why this!

- John Quigley
From: Klaus Harbo
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <47cf99b3$0$15880$edfadb0f@dtext01.news.tele.dk>
·········@gmail.com wrote:
> On Mar 6, 12:01 am, vanekl <·····@acd.net> wrote:
>> Symbols are interned into packages.
>> This is one way to get around the problem:
> 
> Thanks very much for the quick reply!
> 
> Okay, this is fair enough, so by the same token, specifying all
> symbols as keywords both in the file and in test-eq (that is,
> as :GENERAL) will work as well.

That is right, but that would amount to working around the issue rather addressing it, I'd say.

> I just assumed that the reader would implicitly intern any symbols
> into the package in which the call to read occurred, which clearly
> isn't the case.  I remain quite fuzzy as to why this!

Interning occurs at read time.  Consider the difference between

   CL-USER 13 > (defpackage read1 (:use :cl))
   #<The READ1 package, 0/16 internal, 0/16 external>

   CL-USER 14 > (let ((*package* (find-package :read1)))
                  (symbol-package
                   (defun testfn () t)))
   #<The COMMON-LISP-USER package, 108/256 internal, 1/4 external>

and

   CL-USER 15 > (let ((*package* (find-package :read1)))
                  (with-input-from-string (stream "(defun testfn () t)")
                    (symbol-package (eval (read stream)))))
   #<The READ1 package, 3/16 internal, 0/16 external>

and finally, for completeness

   CL-USER 16 > (with-input-from-string (stream "(defun testfn () t)")
                  (symbol-package (eval (read stream))))
   #<The COMMON-LISP-USER package, 110/256 internal, 1/4 external>

   CL-USER 17 >

When you typed the definition of TEST-EQ, the symbol GENERAL was interned into the package current at the time, TEST-PKG 
which explains the results you got.

> - John Quigley

Again, reading up on packages and interning will be well worth your time.

best regards,

-Klaus.
From: ·········@gmail.com
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <6e600ef9-3814-42fb-8860-472c1126247c@x41g2000hsb.googlegroups.com>
All of this is excellent information, Klaus, thanks kindly.
From: Klaus Harbo
Subject: Re: Cross-package symbol equality
Date: 
Message-ID: <47cf93ba$0$15882$edfadb0f@dtext01.news.tele.dk>
·········@gmail.com wrote:
> Would some be good enough to provide insight as to why test-eq returns
> differently based upon which package it's being called from?  A sample
> REPL session below.

I thinking you'll find that reading Ron Garret's excellent guide to CL packages, to be found at 
http://www.flownet.com/ron/packages.pdf, will help you understand this issue.  IMO productive use of Common Lisp 
requires a reasonable grasp of package handling and how symbols are interned -- without it you'll experience endless 
pain with code and data not doing what you expect.

Enjoy!

-Klaus.