Common lisp 参考common lisp中编译时未知的另一个包中的符号

Common lisp 参考common lisp中编译时未知的另一个包中的符号,common-lisp,Common Lisp,有没有一种方法可以在不知道advace中的符号的情况下轻松引用另一个包中的符号 假设我在一个名为MY-package的包中有如下函数 (defun foo-bar (foo bar) `((,foo . foo) (,bar . bar))) 如果我从同一个包调用上面的代码,我将得到如下结果: MY-PACKAGE> (foo-bar 1 2) ((FOO . 1) (BAR . 2)) 如果我从其他包(比如CL-USER)调用它,返回的符号指的是包MY-package:

有没有一种方法可以在不知道advace中的符号的情况下轻松引用另一个包中的符号

假设我在一个名为MY-package的包中有如下函数

(defun foo-bar (foo bar)
  `((,foo . foo)
    (,bar . bar)))
如果我从同一个包调用上面的代码,我将得到如下结果:

MY-PACKAGE> (foo-bar 1 2)
((FOO . 1) (BAR . 2))
如果我从其他包(比如CL-USER)调用它,返回的符号指的是包MY-package:

CL-USER> (my-package:foo-bar 1 2)
((MY-PACKAGE:FOO . 1) (MY-PACKAGE:BAR . 2))
有时,特别是在编写宏时,我希望将函数返回符号插入调用函数的包中(在本例中为CL-USER)。 我能够做到这一点的唯一方法是重写foobar,如下所示

(defun foo-bar (foo bar)
  `((,(intern "FOO" *package*) . ,foo)
    (,(intern "BAR" *package*) . ,bar)))
这很快就会变得难看,特别是当符号作为参数给出时。
有没有更好的方法来处理这个问题?

函数不是从包中调用的。软件包仅由阅读器和创建符号的函数(如INTERN)使用。在调用时,函数的符号已经插入最初读取源代码的包中。因为函数本身并不重要,无论您如何获得它的符号名并调用它

如果您想基于变量*package*的值在不同的包中创建符号,那么您必须这么说。INTERN是创建新符号的方法,包是一个参数。也可以创建符号,而无需将其放入包中


如果符号的包不重要,那么可能需要使用不感兴趣的符号,或者通常是关键字符号。关键字符号插入到包关键字中并自行计算。

如果您确实打算根据上下文将关联列表的关键符号插入到不同的包中,则使用
INTERN
*package*
可以。但是,请注意,
*package*
可能不会绑定到调用的包,除非您显式绑定它。您可以通过定义宏而不是函数来解决这个问题,并在宏扩展时使用
*包*
绑定。

如果这些符号是作为函数调用的参数提供的,那么它们很可能已经存在于函数调用的包中。因此,无需使用
INTERN


如果您对其他方法持开放态度,Rainer的回答提供了很好的建议,例如使用关键字符号,如
:foo
:bar

当symbol包无关紧要时,另一个选择是使用STRING=作为测试。谢谢你的回答Rainer。我知道我可以用实习生,但我想知道这是唯一的选择,还是可以用一种不同于我的方式。我不确定我是否可以使用不感兴趣的符号,因为在某些情况下,我需要比较它们的值。我可以使用关键字符号或者简单地导出我需要的符号,但这并不是我真正想要的。我正在寻找一些类似于
循环
宏的东西,在那里我可以编写例如
(cl:loop for x高达10 collect x)
而不必使用
:for
cl:for
@Marco Righele:您可以简单地替换符号。宏在某个包中获取一个包含内部符号的表达式。然后,它可以以某种方式遍历该表达式,并用标准包中的符号替换特定的内部符号。通常,导致在这些包中创建符号的循环宏的设计不是最好的主意。嗨,Terje。谢谢你的解释。该函数已经是宏的一部分,因此不应该是问题。这些符号(可能)已经被扣留,但我不知道还有什么其他方式可以说“包
X
中的符号
foo
”(调用前X不知道)。
FIND-symbol name&optional package
在包中搜索按名称命名的符号,如果找到,则返回该符号。
name
package
都可以是调用之前未知的字符串。