Prev: A link to a collection of tutorials on LISP.
Next: A link to a collection of tutorials on LISP.
From: Thomas A. Russ on 28 Jun 2010 18:16 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 28 Jun 2010 20:22 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 28 Jun 2010 23:07 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 29 Jun 2010 00:43 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 29 Jun 2010 01:13
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/ |