When a snippet of code depends on a package (optionally) loaded at run-
time, how can I cope with it?
Example of what I'd like to achieve, but doesn't work:
(defun foo ()
(when (find-package :optional)
(optional:bar)))
This fails at compile time because OPTIONAL is not loaded, but BAR is
declared to be from this package.
Leslie P. Polzer wrote:
> When a snippet of code depends on a package (optionally) loaded at run-
> time, how can I cope with it?
>
> Example of what I'd like to achieve, but doesn't work:
>
> (defun foo ()
> (when (find-package :optional)
> (optional:bar)))
>
> This fails at compile time because OPTIONAL is not loaded, but BAR is
> declared to be from this package.
The problem occurs already at READ time. You can bypass this issue by
using intern:
CL-USER> (defun foo ()
(when (find-package :optional)
(funcall (intern "BAR" :optional))))
FOO
CL-USER> (foo)
NIL
Alright.
CL-USER> (defpackage :optional (:use :cl))
#<PACKAGE "OPTIONAL">
CL-USER> (in-package :optional)
#<PACKAGE "OPTIONAL">
OPTIONAL> (defun bar () t)
BAR
And there you go:
OPTIONAL> (in-package :cl-user)
#<PACKAGE "COMMON-LISP-USER">
CL-USER> (foo)
T
HTH,
Peter
"Leslie P. Polzer" <·············@gmx.net> writes:
> When a snippet of code depends on a package (optionally) loaded at run-
> time, how can I cope with it?
Do the interning of your symbol at runtime instead of at read time.
> (defun foo ()
> (when (find-package :optional)
> (optional:bar)))
(defun foo ()
(when (find-package :optional)
(funcall (intern "BAR" :optional))))
...Peder...
--
This must be Thursday. I never could get the hang of Thursdays.
Peder O. Klingenberg <·····@news.klingenberg.no> wrote:
+---------------
| "Leslie P. Polzer" <·············@gmx.net> writes:
| > When a snippet of code depends on a package (optionally)
| > loaded at runtime, how can I cope with it?
|
| Do the interning of your symbol at runtime instead of at read time.
|
| (defun foo ()
| (when (find-package :optional)
| (funcall (intern "BAR" :optional))))
+---------------
Or if you might be using case-sensitive reading [e.g., setting
readtable-case to :INVERT, as some people do to deal with CamelCase],
you could even do this:
(defun foo ()
(when (find-package :optional)
(funcall (intern (symbol-name :bar) :optional))))
I use a version of this sometimes in my LHP (Lisp-Handled Pages)
web application infrastructure, when the LHP page being loaded
is big enough (or sufficiently in flux during development) to
potentially need an ASDF update each time it's accessed:
;;; Boilerplate for using ASDF from LHP page.
(let ((system :foo-web)
(package :org.rpw3.foo)
(function :foo-main))
(flet ((this-page (request)
;; Ensure up-to-date each time
(asdf:operate 'asdf:load-op system)
;; Call the request handler
(funcall (intern (symbol-name function) package) request)))
;; LHP pages must set the page-handling function while loading.
(lhp-set-page-function #'this-page)))
Yes, it's somewhat inefficient, but it's *awfully* convenient
while developing a new web app. Make an edit, hit "Reload" on
the web browser, and all the right things get recompiled/reloaded
and the page is refreshed with the output of the new code.
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607