From: Thomas A. Russ on
Peter Keller <psilord(a)cs.wisc.edu> writes:
>
> So, I've gotten a solution to work. The gist of my solution is:
>
> ;; on the master process side (transformed example, picked out of a hairy
> ;; macro which produces it):
>
> (make-structure
> :pkge (package-name (symbol-name 'foo))
> :func (symbol-name 'foo))
>
> Then I serialize the structure across the network:

What are you using for serialization? Do you use your own serialization
protocol? The correctly printed serialization of a lisp symbol will
include the package prefix if it is deemed necessary.

So why not just use the built-in print/read functionality to transfer the
information, since this involves lisp.

You just need to make sure (by convention) that you use the same
*package* setting for both serialization and deserialization. One
method for doing this is to bind *package* to the keyword package on
both the writing and reading side:

(let ((*package* (find-package "KEYWORD")))
... Code to write the lisp forms to a socket ...)

(let ((*package* (find-package "KEYWORD")))
... Code to read the lisp forms from a socket ...)

> ;; on the slave process side (don't forget it is the same executable just on
> ;; a different machine):
>
> (let* ((pkge (structure-pkge struct))
> (func (structure-func struct))
> (sym-func (intern func (intern pkge :keyword))))
>
> (apply (symbol-function sym-func) args))

Well, if you just send the symbol as an appropriate lisp s-expression,
then you can get all of this done for you by the reader and the writer.
You just need to make sure you read and write with the same package
settings.

> Notice the interesting use of intern to get the symbol in the package I need
> and then symbol-function to get the contents of said symbol (which I know to be
> a function so I don't have to check).

> I've also stumbled across some very arcane cases of unexpected symbol
> internship into various packages with a macro expanding into a macro across
> package boundaries that makes me frustrated.

Well, it shouldn't be arcane.

Any symbol that is READ by the lisp reader will be in the package that
is current at the time the symbol is read.

Any call to INTERN will intern the symbol in the package you specify (or
the current package if you don't name one).

Where it can get complicated is when you start constructing symbols as
part of your macro-expansion. The key is to remember that the current
package will be the controlling factor unless you explicitly provide it
to an appropriate function call.

It is also important to realize that a macro invocation is read (and
thus has all symbol mapping of the form that is the macro invocation)
before it is expanded. So nothing you do inside your macro will affect
the interning of any symbols that are arguments to your macro.

--
Thomas A. Russ, USC/Information Sciences Institute
From: RG on
In article <ymi6312951b.fsf(a)blackcat.isi.edu>,
tar(a)sevak.isi.edu (Thomas A. Russ) wrote:

> Any symbol that is READ by the lisp reader will be in the package that
> is current at the time the symbol is read.

No. Only strings that do not include a package specifier will produce
symbols interned in the current package.

You made another similar mistake in another posting:

> Packages affect the READing of symbols. They don't affect other
> operations like MAKE-SYMBOL or intern

That's not true either. INTERN in particular is intimately related to
packages.

You really ought to get a better grip on the facts before you start to
offer advice to newbies or you will do more harm than good.

rg
From: Pascal J. Bourguignon on
Peter Keller <psilord(a)cs.wisc.edu> writes:

> RG <rNOSPAMon(a)flownet.com> wrote:
>> If you think this is odd then you have missed something very
>> fundamental. Packages have nothing to do with bindings, so it is not at
>> all odd that explanations of packages should have nothing to do with
>> bindings.
>
> What's the point of exporting a symbol if you don't care about either its
> binding or the fact it is eq to itself inside of the library the package is
> for? It is my understanding the keyword package is an specialization of the
> latter idea.
>
>> Packages are just data structures that map strings onto symbols. Don't
>> make it more complicated than it is.
>
> Saying it isn't more complicated than it is is somewhat disingenuous. I say.
> this because because the string "A::B" turns into the symbol |A::B| with
> make-symbol and you can't get the binding for it as you'd expect because what
> you really wanted was |A|::|B|. This notion right here is what I spent a good
> long time figuring out and understanding. The part that finally made me figure
> it out was realizing that A::B is often and erronously loosely talked about
> like the entire thing is a symbol, but it isn't, It is the symbol B with a
> package prefix A.
>
> This is the difference between (intern "A" "B") and (intern "A::B").
>
> Once I really understood that difference, I understood many of the problems I
> was having. Hence this is why one should be careful talking about strings as
> being mapped into symbols and should make mention that package prefixes with
> the colons are not a part of the symbol name. In addition, this is why I was a
> bit confused by Pascal's PRINT-READABLY solution, I kept grouping the package
> prefix and symbol name into the whole thing being a symbol, and that was wrong.

Notice that a symbol has ONE name, but it doesn't have ONE package.
The same symbol may be accessible from 0, 1, or more packages. And
this is independent from the fact that a symbol may have or not a home
package.




C/USER[48]> (let ((s (make-symbol "B"))
(q (progn (ignore-errors (delete-package "Q")) (make-package "Q" :use '())))
(p (progn (ignore-errors (delete-package "P")) (make-package "P" :use '()))))
(print s)
(import s p)
(print s)
(export s p)
(print s)
(import s q)
(assert (eq s (intern "B" "P")))
(assert (eq s (intern "B" "Q")))
(print s)
(print (symbol-package s))
(delete-package "P")
(print s)
(print (symbol-package s))
(read-from-string "Q::B"))

#:B
P::B
P:B
P:B
; B can be read as |P|:|B|, |P|::|B| or |Q|::|B|
; also, if *package* is bound to the package P or Q,
; it can be read as |B|.
#<PACKAGE P> ; B has a home package
#:B
NIL ; B has no home package
#:B ; ; but B can still be read as |Q|::|B|
4



Also, the symbol read as P:B may be different from the symbol read as P:B

(let ((p (progn (ignore-errors (delete-package "PACK"))
(make-package "PACK" :use '()))))
(let ((s (let ((*package* p)) (read-from-string "PACK::SYMB"))))
(print `(s = ,s))
(unintern s p)
(let ((r (let ((*package* p)) (read-from-string "PACK::SYMB"))))
(print `(((eq r s) = ,(eq r s)) (r = ,r) (s = ,s))))))

(S = PACK::SYMB)
(((EQ R S) = NIL) (R = PACK::SYMB) (S = #:SYMB))


Two symbols may have the same name, as you can see above, the symbols
bound to the variables r and s have the name "SYMB".

A symbol has only one name and it cannot change.

But a symbol may have zero, one or more packages, and they can change.



--
__Pascal Bourguignon__ http://www.informatimago.com/
From: Peter Keller on
Pascal J. Bourguignon <pjb(a)informatimago.com> wrote:
> Also, the symbol read as P:B may be different from the symbol read as P:B
>
> (let ((p (progn (ignore-errors (delete-package "PACK"))
> (make-package "PACK" :use '()))))
> (let ((s (let ((*package* p)) (read-from-string "PACK::SYMB"))))
> (print `(s = ,s))
> (unintern s p)
> (let ((r (let ((*package* p)) (read-from-string "PACK::SYMB"))))
> (print `(((eq r s) = ,(eq r s)) (r = ,r) (s = ,s))))))
>
> (S = PACK::SYMB)
> (((EQ R S) = NIL) (R = PACK::SYMB) (S = #:SYMB))
>
>
> Two symbols may have the same name, as you can see above, the symbols
> bound to the variables r and s have the name "SYMB".
>
> A symbol has only one name and it cannot change.
>
> But a symbol may have zero, one or more packages, and they can change.

While I don't understand the mechanism for why PACK::SYMB is a different symbol
(I would propose some internal serial number on read-from-string gets
incremented if the symbol wasn't there when one is needed), I do (now)
understand the semantics in your example.

Thank you for the explanation.

-pete
From: Pascal J. Bourguignon on
Peter Keller <psilord(a)cs.wisc.edu> writes:

> Pascal J. Bourguignon <pjb(a)informatimago.com> wrote:
>> Also, the symbol read as P:B may be different from the symbol read as P:B
>>
>> (let ((p (progn (ignore-errors (delete-package "PACK"))
>> (make-package "PACK" :use '()))))
>> (let ((s (let ((*package* p)) (read-from-string "PACK::SYMB"))))
>> (print `(s = ,s))
>> (unintern s p)
>> (let ((r (let ((*package* p)) (read-from-string "PACK::SYMB"))))
>> (print `(((eq r s) = ,(eq r s)) (r = ,r) (s = ,s))))))
>>
>> (S = PACK::SYMB)
>> (((EQ R S) = NIL) (R = PACK::SYMB) (S = #:SYMB))
>>
>>
>> Two symbols may have the same name, as you can see above, the symbols
>> bound to the variables r and s have the name "SYMB".
>>
>> A symbol has only one name and it cannot change.
>>
>> But a symbol may have zero, one or more packages, and they can change.
>
> While I don't understand the mechanism for why PACK::SYMB is a different symbol
> (I would propose some internal serial number on read-from-string gets
> incremented if the symbol wasn't there when one is needed), I do (now)
> understand the semantics in your example.

That's because of UNINTERN, which removes the symbol bound to the
variable S, from the mapping in the package PACK with the symbol name
"SYMB". At this moment, the symbol bound to the variable S is
homeless, that's why it's printed as #:SYMB.

When we read the second time the same string, INTERN is called again,
but and again, since there's no symbol mapped from the "SYMB" symbol
name in the package PACK, INTERN creates a new symbol with that name,
and puts it into the map. Thus the symbol bound to the variable R is
a new symbol, different from the one bound to the variable S. Both
have the same name, and both were or are at some time interned in the
package PACk, but when the symbol bound to the variable R is interned
in PACK, the symbol bound to the variable S is not interned in PACK.


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