Reputation: 2862
Is there a way to easily refer symbols in another other package without knowing it in advace ?
Let's say that I have a function like the following in a package names MY-PACKAGE
(defun foo-bar (foo bar)
`((,foo . foo)
(,bar . bar)))
If I call the above from the same package I'll get something like the following:
MY-PACKAGE> (foo-bar 1 2)
((FOO . 1) (BAR . 2))
If I call it from some other package, let's say CL-USER, the symbol returned refer to the package MY-PACKAGE:
CL-USER> (my-package:foo-bar 1 2)
((MY-PACKAGE:FOO . 1) (MY-PACKAGE:BAR . 2))
Sometimes, expecially when writing macros, I'd like to have the function return symbol interned in the package from which the function has been called (in this case CL-USER). The only way I have been able to do this is by rewriting foo-bar as follows
(defun foo-bar (foo bar)
`((,(intern "FOO" *package*) . ,foo)
(,(intern "BAR" *package*) . ,bar)))
This gets ugly very soon, expecially when the symbols are given as parameters. Is there any better way to handle this ?
Upvotes: 3
Views: 706
Reputation: 3689
Using INTERN
with *package*
is fine if you really intend to intern the key symbol of the association list in a different package depending on the context. However, note that *package*
may not be bound to the package of the call unless you bind it explicitly. You can resolve that by defining a macro instead of a function and use the *package*
binding at macro expansion time.
If the symbols are given as parameters to the function call, they are likely already interned in the package of the function call. Hence there is no need to use INTERN
.
In case you are open to alternative approaches, Rainer's answer provides good suggestions such as using keyword symbols like :foo
and :bar
instead.
Upvotes: 1
Reputation: 139411
Functions are not called from a package. Packages are only used by the reader and by symbol creating functions like INTERN. At call time the symbols of a function are already interned in the package where the source code was originally read. For the function itself is does not matter how you get it's symbol name and call it.
If you want to create symbols in different packages based on, say, the value of the variable *package*, then you have to say so. INTERN is the way to create new symbols and the package is a parameter. It is also possible to create symbols without interning them in a package.
If the package for the symbol does not matter, then one might want to use uninterned symbols or, typically, keyword symbols. Keyword symbols are interned in the package keyword and evaluate to themselves.
Upvotes: 1