[This is probably better asked on the TBNL mailing list.]
On Fri, 10 Feb 2006 21:15:19 +1000, Igor Plekhov penguin@ocean.vvo.ru wrote:
In TBNL some functions are created to handle incoming requests.
Functions are created? You're talking about your own handlers or something else?
What package are they executed in? I.e. what package *PACKAGE* is bound to? How can I control it?
In your own functions you can rebind *PACKAGE* to your liking.
(let ((*package* (my-function))) ;; do something )
For existing TBNL functions the package shouldn't matter with the exception of READ-FROM-STRING* the behaviour of which is documented:
http://weitz.de/tbnl/#read-from-string*
Does that answer your question or am I misunderstanding?
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
I'm guessing this is what I just ran into and the answer is your new function names and symbols will be interned in :CL-USER :) I'd love to know how to change that, but haven't bothered to dig yet. (in my case, :CL-USER would be my second choice after one of my own packages)
In my case, I had code that uses the multi-method dispatch mechanism to display the right page (I'm not yet sure if thats a good idea :) something like this:
(defmethod display-page (page-name (eql 'login-page)) ... )
To convert the text strings given by the user into the right symbol (so this dispatch mecnhanism can work), I must intern them in the :CL-USER package.
This did take me a while to figure out and *I* couldn't find it in the documentation anywhere. (I guess, maybe, it should have been obvious, but I still consider myself mostly a Lisp newbie). I believe my CMUCL Lisp starts with a core file causing it to start in :Jims-PackageA, then I've been loading a file (that causes TBNL and all that good stuff to be loaded) and immediately switching to :Jims-PackageB, so it was really confusing to be using the :CL-USER package at all. :)
I hope this helps, Jim
James E. Prewett Jim@Prewett.org download@hpc.unm.edu Systems Team Leader LoGS: http://www.hpc.unm.edu/~download/LoGS/ Designated Security Officer OpenPGP key: pub 1024D/31816D93 HPC Systems Engineer III UNM HPC 505.277.8210
On Fri, 10 Feb 2006, Edi Weitz wrote:
[This is probably better asked on the TBNL mailing list.]
On Fri, 10 Feb 2006 21:15:19 +1000, Igor Plekhov penguin@ocean.vvo.ru wrote:
In TBNL some functions are created to handle incoming requests.
Functions are created? You're talking about your own handlers or something else?
What package are they executed in? I.e. what package *PACKAGE* is bound to? How can I control it?
In your own functions you can rebind *PACKAGE* to your liking.
(let ((*package* (my-function))) ;; do something )
For existing TBNL functions the package shouldn't matter with the exception of READ-FROM-STRING* the behaviour of which is documented:
http://weitz.de/tbnl/#read-from-string*
Does that answer your question or am I misunderstanding? _______________________________________________ tbnl-devel site list tbnl-devel@common-lisp.net http://common-lisp.net/mailman/listinfo/tbnl-devel
On Fri, 10 Feb 2006 06:25:45 -0700 (MST), Jim Prewett download@hpc.unm.edu wrote:
I'm guessing this is what I just ran into and the answer is your new function names and symbols will be interned in :CL-USER :) I'd love to know how to change that, but haven't bothered to dig yet. (in my case, :CL-USER would be my second choice after one of my own packages)
In my case, I had code that uses the multi-method dispatch mechanism to display the right page (I'm not yet sure if thats a good idea :) something like this:
(defmethod display-page (page-name (eql 'login-page)) ... )
To convert the text strings given by the user into the right symbol (so this dispatch mecnhanism can work), I must intern them in the :CL-USER package.
This did take me a while to figure out and *I* couldn't find it in the documentation anywhere. (I guess, maybe, it should have been obvious, but I still consider myself mostly a Lisp newbie). I believe my CMUCL Lisp starts with a core file causing it to start in :Jims-PackageA, then I've been loading a file (that causes TBNL and all that good stuff to be loaded) and immediately switching to :Jims-PackageB, so it was really confusing to be using the :CL-USER package at all. :)
Hmm. It /seems/ to me that both of you are rather talking about general problems with packages and not about TBNL in particular. TBNL itself never interns symbols except when it creates keywords, and in this case the package is clearly defined.
You should always create your own package to work in if you write code, don't use CL-USER. See test.lisp in TBNL for an example.
If your code looks like this
(defmethod display-page (page-name (eql 'login-page)) ... )
then LOGIN-PAGE will be a symbol accessible in the package you're in, i.e. the package of the file the method is defined in (assuming you used LOAD to load the file). In 99.9% of all cases this should be the package you find in the very first line starting with IN-PACKAGE. If you don't have such a line there - see above... :)
Sorry if that sounds patronizing, maybe I'm again missing the point.
Cheers, Edi.
I think you're missing the point Edi :)
Here is a simple example that I think gets to the heart of the problem: I'm certainly not claiming that this isn't a problem with my understanding, however :)
When you visit /foo, the webpage returned displays this text: "package: #<The COMMON-LISP-USER package>"
What I'm not understanding is *why* that is what is displayed. I would have hoped for "package: #<MYPACKAGE package>".
(defpackage :mypackage) (in-package :mypackage)
(defun some-func () (cl-who:with-html-output-to-string (*standard-output* nil :prologue nil :indent nil) (:HTML (:HEAD (:TITLE "foo")) (:BODY (cl-who:str (CL-WHO:ESCAPE-STRING (format () "package: ~A" *package*)))))))
(setq tbnl:*dispatch-table* (list (tbnl:create-prefix-dispatcher "/foo" #'some-func)))
Jim
James E. Prewett Jim@Prewett.org download@hpc.unm.edu Systems Team Leader LoGS: http://www.hpc.unm.edu/~download/LoGS/ Designated Security Officer OpenPGP key: pub 1024D/31816D93 HPC Systems Engineer III UNM HPC 505.277.8210
On Fri, 10 Feb 2006, Edi Weitz wrote:
On Fri, 10 Feb 2006 06:25:45 -0700 (MST), Jim Prewett download@hpc.unm.edu wrote:
I'm guessing this is what I just ran into and the answer is your new function names and symbols will be interned in :CL-USER :) I'd love to know how to change that, but haven't bothered to dig yet. (in my case, :CL-USER would be my second choice after one of my own packages)
In my case, I had code that uses the multi-method dispatch mechanism to display the right page (I'm not yet sure if thats a good idea :) something like this:
(defmethod display-page (page-name (eql 'login-page)) ... )
To convert the text strings given by the user into the right symbol (so this dispatch mecnhanism can work), I must intern them in the :CL-USER package.
This did take me a while to figure out and *I* couldn't find it in the documentation anywhere. (I guess, maybe, it should have been obvious, but I still consider myself mostly a Lisp newbie). I believe my CMUCL Lisp starts with a core file causing it to start in :Jims-PackageA, then I've been loading a file (that causes TBNL and all that good stuff to be loaded) and immediately switching to :Jims-PackageB, so it was really confusing to be using the :CL-USER package at all. :)
Hmm. It /seems/ to me that both of you are rather talking about general problems with packages and not about TBNL in particular. TBNL itself never interns symbols except when it creates keywords, and in this case the package is clearly defined.
You should always create your own package to work in if you write code, don't use CL-USER. See test.lisp in TBNL for an example.
If your code looks like this
(defmethod display-page (page-name (eql 'login-page)) ... )
then LOGIN-PAGE will be a symbol accessible in the package you're in, i.e. the package of the file the method is defined in (assuming you used LOAD to load the file). In 99.9% of all cases this should be the package you find in the very first line starting with IN-PACKAGE. If you don't have such a line there - see above... :)
Sorry if that sounds patronizing, maybe I'm again missing the point.
Cheers, Edi.
On Fri, 10 Feb 2006 08:52:20 -0700 (MST), Jim Prewett download@hpc.unm.edu wrote:
I think you're missing the point Edi :)
I don't... :)
Here is a simple example that I think gets to the heart of the problem: I'm certainly not claiming that this isn't a problem with my understanding, however :)
When you visit /foo, the webpage returned displays this text: "package: #<The COMMON-LISP-USER package>"
What I'm not understanding is *why* that is what is displayed. I would have hoped for "package: #<MYPACKAGE package>".
(defpackage :mypackage) (in-package :mypackage)
(defun some-func () (cl-who:with-html-output-to-string (*standard-output* nil :prologue nil :indent nil) (:HTML (:HEAD (:TITLE "foo")) (:BODY (cl-who:str (CL-WHO:ESCAPE-STRING (format () "package: ~A" *package*)))))))
(setq tbnl:*dispatch-table* (list (tbnl:create-prefix-dispatcher "/foo" #'some-func)))
Why should it display #<MYPACKAGE package>? *PACKAGE* is a runtime concept, it's not a literal constant that's hard-coded into the function when you compile it:
CL-USER 1 > (defpackage :foo (:use :cl)) #<PACKAGE FOO>
CL-USER 2 > (in-package :foo) #<PACKAGE FOO>
FOO 3 > (defun foo () *package*) FOO
FOO 4 > (foo) #<PACKAGE FOO>
FOO 5 > (in-package :cl-user) #<PACKAGE COMMON-LISP-USER>
CL-USER 6 > (foo::foo) #<PACKAGE COMMON-LISP-USER>
The package you see in your example depends on how (from where) you started TBNL and how (from where) the thread that handles the request is invoked. The ANSI standard doesn't specify the package newly created threads start in (because it doesn't mention MP) but your Lisp's documentation will probably tell you. I think it's not unusual (and makes sense) to just re-bind *PACKAGE* to *PACKAGE*.
So, the important part is missing in your example above: When and how did you invoke TBNL:START-TBNL? I bet you did that from CL-USER and you will see a different result if you start it from MYPACKAGE.
If you're doing something with packages at runtime you should always re-bind *PACKAGE* - or in the case of INTERN you should use its second argument.
Cheers, Edi.
Ah-Ha! It must be something to do with the threads as you say.
I seem to get the same result reguardless of which package I start TBNL from. FWIW, I'm using CMU Common Lisp 19b (19B) on FreeBSD 4.11-STABLE.
I still get the same result reguardless of which package I start TBNL from. My file now looks like this:
(defpackage :mypackage) (in-package :mypackage)
(tbnl:start-tbnl)
(defun some-func () (cl-who:with-html-output-to-string (*standard-output* nil :prologue nil :indent nil) (:HTML (:HEAD (:TITLE "foo")) (:BODY (cl-who:str (CL-WHO:ESCAPE-STRING (format () "package: ~A" *package*)))))))
(setq tbnl:*dispatch-table* (list (tbnl:create-prefix-dispatcher "/foo" #'some-func)))
Why should it display #<MYPACKAGE package>? *PACKAGE* is a runtime concept, it's not a literal constant that's hard-coded into the function when you compile it:
Right. The point of my example was to show that, at runtime, *PACKAGE* seems to always be bound to :COMMON-LISP-USER for any function I run inside of TBNL. My cureosity is why does that happen; while I haven't yet looked at the CMUCL thread documentation, my guess is that it is related to threads.
The package you see in your example depends on how (from where) you started TBNL and how (from where) the thread that handles the request is invoked.
Under CMUCL, I see that the former (where TBNL is started) has no effect. My guess is that, for whatever reason, the thread is launched in the :COMMON-LISP-USER package.
So, the important part is missing in your example above: When and how did you invoke TBNL:START-TBNL? I bet you did that from CL-USER and you will see a different result if you start it from MYPACKAGE.
It doesn't seem to matter. :) In my original email, I stated that my Lisp environment is set up such that I *NEVER* see the CL-USER package which is why I found it so strange that *PACKAGE* would ever be set to :COMMON-LISP-USER!
If you're doing something with packages at runtime you should always re-bind *PACKAGE* - or in the case of INTERN you should use its second argument.
Thats probably the advice I was looking for :) Sorry for being so dense :)
Jim
On Fri, 10 Feb 2006 10:52:20 -0700 (MST), Jim Prewett download@hpc.unm.edu wrote:
Ah-Ha! It must be something to do with the threads as you say.
FWIW, it might also be related to how KMRCL invokes the threads. I saw different packages when I tried your example with LispWorks.
(we are now well outside of TBNL land...)
Jim Prewett wrote:
When you visit /foo, the webpage returned displays this text: "package: #<The COMMON-LISP-USER package>"
I experienced a nasty bug awhile back caused by similar confusion. I was reading from a stream at runtime and expecting the package to be bound to the package in effect in the source code. Wrong. Or at least, wrong some of the time, which caused a debugging nightmare: the code worked correctly when started from SLIME, but failed when SBCL was started by my init scripts. It took me some time to understand what was going on.
What I'm not understanding is *why* that is what is displayed.
The explanation is this: IN-PACKAGE only binds *package* at compile-time. At runtime, it is your responsibility to ensure the correct package is dynamically bound.
The hyperspec does not make this point very clearly at all.
If you are reading symbols at runtime for the purpose of comparison, I recommend using the keyword package. The example then becomes something more akin to:
(defpackage :mypackage (:use :cl)) (in-package :mypackage)
(defun some-func () (cl-who:with-html-output-to-string (*standard-output* nil :prologue nil :indent nil) (:html (:head (:title "foo")) (:body (cl-who:str (cl-who:escape-string (let ((*package* (find-package :keyword))) (format nil "package: ~a~%query=BAR?: ~a~%" *package* (eq :bar (intern (or (tbnl:parameter "query") "BAR")))))))))))
(setq tbnl:*dispatch-table* (list (tbnl:create-prefix-dispatcher "/tbnl/foo" #'some-func)))
Cheers,
-- Travis
On Fri, 10 Feb 2006 12:23:35 -0500, Travis Cross travis@crosswirecorp.com wrote:
(let ((*package* (find-package :keyword))) (format nil "package: ~a~%query=BAR?: ~a~%" *package* (eq :bar (intern (or (tbnl:parameter "query") "BAR")))))
Or simply
(intern (or (tbnl:parameter "query") "BAR") :keyword)