Prev: A link to a collection of tutorials on LISP.
Next: A link to a collection of tutorials on LISP.
From: Pascal J. Bourguignon on 27 Jun 2010 19:25 Peter Keller <psilord(a)cs.wisc.edu> writes: > In my case, I've implemented a master/worker paradigm with distributed > processes. The master process packs up the worker's task data along with the > symbol associated with the function on the worker side and sends it to the > worker process in an RPC-like model. I use cl-serializer, so I actually do send > the target function's symbol to the client side, which arrives uninterned--it > could just have easily been the string of the function's name though. So you are reading symbol names. You have strings, not symbols to start with, and this is a reading problem. Why didn't you tell first? The easy solution, is to set *PRINT-READABLY* true when you serialize your function names: (in-package :cl-user) (let ((*print-readably* t)) (print 'y::sz)) prints: |Y|::|SZ| So that there may be no ambiguity on the reading side. If you don't want to do that (I'd wonder why?), then you would have to make assumptions on the reading side, such as, in what package should unqualified symbols be read, and with what readtable-case setting? For example: (with-standard-io-syntax (let ((*package* (find-package "Y"))) (read-from-string "sz"))) --> Y::SZ > My problem lies in that the master/worker library is package X, and the > application built on it is package Y. No, this is irrelevant. > I suppose I could bind the value of *package* into the task structure from the > master to the worker, and the worker could use that while interning the symbol > same and using symbol-function on it, but I went down that road for a bit and > couldn't get it working. Should I try again? Yes. But my advice is to use *print-readably* = true. > In C, I would just associate a function pointer with the string in a hash table > and use that since there is no notion of namespaces (and don't forget the > master and worker are the exact same executable). In Lisp (to which I'm new), > it is confounded somewhat, so I'd like to know how to solve it. Imagine you have several hash-tables! Each package is one map from symbol names to symbols, often different symbols. -- __Pascal Bourguignon__ http://www.informatimago.com/
From: Scott L. Burson on 27 Jun 2010 19:39 On Jun 27, 4:06 pm, Peter Keller <psil...(a)cs.wisc.edu> wrote: > In my case, I've implemented a master/worker paradigm with distributed > processes. The master process packs up the worker's task data along with the > symbol associated with the function on the worker side and sends it to the > worker process in an RPC-like model. I use cl-serializer, so I actually do send > the target function's symbol to the client side, which arrives uninterned--it > could just have easily been the string of the function's name though. I haven't used cl-serializer, but I would suggest it is standard practice for a serializer to preserve the package of a serialized symbol. Certainly the Lisp printer/reader can be made to do this easily enough, and a high-speed binary serializer I once wrote did it as well. It seems odd that cl-serializer does not. Perhaps there is some option you can set to cause it to do so? > I suppose I could bind the value of *package* into the task structure from the > master to the worker, and the worker could use that while interning the symbol > same and using symbol-function on it, but I went down that road for a bit and > couldn't get it working. Should I try again? My suggestion at this point would be first to try to get cl-serializer to do the right thing, but if that proves difficult for some reason, try to do this -- or maybe try a different serializer :) (Really, the first thing to ask yourself is whether the Lisp printer/ reader is an adequate serializer for your purposes.) -- Scott
From: Peter Keller on 27 Jun 2010 20:04 Pascal J. Bourguignon <pjb(a)informatimago.com> wrote: > Peter Keller <psilord(a)cs.wisc.edu> writes: > >> In my case, I've implemented a master/worker paradigm with distributed >> processes. The master process packs up the worker's task data along with the >> symbol associated with the function on the worker side and sends it to the >> worker process in an RPC-like model. I use cl-serializer, so I actually do send >> the target function's symbol to the client side, which arrives uninterned--it >> could just have easily been the string of the function's name though. > > So you are reading symbol names. You have strings, not symbols to > start with, and this is a reading problem. Why didn't you tell first? Ah, you misunderstand, I really do have the symbol names for the functions. I have an easy choice between the unqualified symbolic name of a function, or the unqualified string representation of the funtion's name. From your response, however, it looks like my problem is that they are unqualified. > The easy solution, is to set *PRINT-READABLY* true when you serialize > your function names: > > (in-package :cl-user) > (let ((*print-readably* t)) > (print 'y::sz)) > > prints: > > |Y|::|SZ| > > So that there may be no ambiguity on the reading side. > If you don't want to do that (I'd wonder why?), then you would have to > make assumptions on the reading side, such as, in what package should > unqualified symbols be read, and with what readtable-case setting? > > For example: > > (with-standard-io-syntax > (let ((*package* (find-package "Y"))) > (read-from-string "sz"))) > > --> Y::SZ The common idea in both of these solutions you've provided is that the SZ symbol is qualified with a package name. So, basically, when I'm storing the symbol of the function I need to call, I need to store the fully qualified name of the symbol. Then on the client side, the invocation of it will pick it from the right package properly. >> My problem lies in that the master/worker library is package X, and the >> application built on it is package Y. > > No, this is irrelevant. I think I might have a small understanding of why you said this. But I'll need to experiment a bit more to really understand it. Thank you for your help. I'll try out some of the above and see if I learn something. At least after a bit, if I continue not to understand, I'll probably be able to state my question more precisely. -pete
From: Peter Keller on 27 Jun 2010 20:17 Scott L. Burson <gyro(a)zeta-soft.com> wrote: > On Jun 27, 4:06?pm, Peter Keller <psil...(a)cs.wisc.edu> wrote: > I haven't used cl-serializer, but I would suggest it is standard > practice for a serializer to preserve the package of a serialized > symbol. Certainly the Lisp printer/reader can be made to do this > easily enough, and a high-speed binary serializer I once wrote did it > as well. It seems odd that cl-serializer does not. Perhaps there is > some option you can set to cause it to do so? I have no idea. It seems likely not since there are exactly two functions that it exports: serialize, and deserialize. :) > My suggestion at this point would be first to try to get cl-serializer > to do the right thing, but if that proves difficult for some reason, > try to do this -- or maybe try a different serializer :) I can ask around in #iolib, I think one of the people there might have had a hand in writing it. > (Really, the first thing to ask yourself is whether the Lisp printer/ > reader is an adequate serializer for your purposes.) I need something to serialize almost arbitrary lisp forms down to an unsigned byte array since it makes my network communications infintely easier to perform. -pete
From: Pascal J. Bourguignon on 27 Jun 2010 20:58
Peter Keller <psilord(a)cs.wisc.edu> writes: > Pascal J. Bourguignon <pjb(a)informatimago.com> wrote: >> Peter Keller <psilord(a)cs.wisc.edu> writes: >> >>> In my case, I've implemented a master/worker paradigm with distributed >>> processes. The master process packs up the worker's task data along with the >>> symbol associated with the function on the worker side and sends it to the >>> worker process in an RPC-like model. I use cl-serializer, so I actually do send >>> the target function's symbol to the client side, which arrives uninterned--it >>> could just have easily been the string of the function's name though. >> >> So you are reading symbol names. You have strings, not symbols to >> start with, and this is a reading problem. Why didn't you tell first? > > Ah, you misunderstand, I really do have the symbol names for the functions. Symbol names are strings: (typep (symbol-name 'toto) 'string) --> T When you serialize, using PRINT and deserializing using READ, you are converting lisp objects to sequences of characters and back. And STRINGs are sequences of characters. Don't let you be misled by the fact that some sequences of character are "dynamic", transmitted on sockets, ttys, or files, in time, while the others are stored statically in memory. > I have an easy choice between the unqualified symbolic name of a > function, or the unqualified string representation of the funtion's > name. > > From your response, however, it looks like my problem is that they are > unqualified. > >> The easy solution, is to set *PRINT-READABLY* true when you serialize >> your function names: >> >> (in-package :cl-user) >> (let ((*print-readably* t)) >> (print 'y::sz)) >> >> prints: >> >> |Y|::|SZ| >> >> So that there may be no ambiguity on the reading side. > >> If you don't want to do that (I'd wonder why?), then you would have to >> make assumptions on the reading side, such as, in what package should >> unqualified symbols be read, and with what readtable-case setting? >> >> For example: >> >> (with-standard-io-syntax >> (let ((*package* (find-package "Y"))) >> (read-from-string "sz"))) >> >> --> Y::SZ > > The common idea in both of these solutions you've provided is that the SZ > symbol is qualified with a package name. > > So, basically, when I'm storing the symbol of the function I need to call, I > need to store the fully qualified name of the symbol. Then on the client > side, the invocation of it will pick it from the right package properly. If you are "storing" a symbol, you don't need anything else than the symbol A symbol can even have no package! (defun g (fname) (format t "I will call the function named ~A (~:*~S)~%" fname) (funcall fname)) (let ((fname (gensym))) (setf (symbol-function fname) (lambda () (print 'hi))) (g fname)) prints: | I will call the function named G11357 (#:G11357) | | HI (defun y::f () (print '(hi from y))) (g 'y::f) prints: | I will call the function named F (Y::F) | | (HI FROM Y) Again, qualification only matters when you are READing a symbol, that is, when you are deserializing it. And when you are PRINTing a symbol, you can do so READABLY, so that qualification is produced, and ambiguity removed. >>> My problem lies in that the master/worker library is package X, and the >>> application built on it is package Y. >> >> No, this is irrelevant. > > I think I might have a small understanding of why you said this. But I'll need > to experiment a bit more to really understand it. What could matter, is that PRINTing and READing occurs with two different setting of the current package, *PACKAGE*. If you bound *PACKAGE* to the same one at both ends, you could get more consistent results. For example, using WITH-STANDARD-IO-SYNTAX, which binds *PACKAGE* to the CL-USER package and *PRINT-READABLY* to true. > Thank you for your help. I'll try out some of the above and see if I learn > something. > > At least after a bit, if I continue not to understand, I'll probably be able to > state my question more precisely. > > -pete -- __Pascal Bourguignon__ http://www.informatimago.com/ |