我想要的只是为swank加载一个初始化文件,这个文件在没有swank的情况下启动时不会影响我的lisp ......
我首先在我的文件中尝试了#+ swank(defun ...),这是从ccl-init加载的(在ccl 1.10 + windows上尝试这个),很快就意识到它是在swank加载之前来源的(显然)。
我的目标是在每次开始swank时定义一个简单的函数:cl-user。我刚刚用一个swank add-hook来加载我的init.lisp文件,因为我想在cl-user中定义函数,我在init.lisp中尝试了这个:
(let ((current-package *package*))
(in-package :cl-user)
(defun cd (dir)
(swank:set-default-directory
(parse-namestring dir)))
(in-package current-package))
现在,我不记得是否允许在let中使用defun,但是lisp不会抱怨它,而是告诉我cur-pck符号不存在,而且当我们切换包时, cur-pck绑定超出范围。我认为cur-pck是一个词法绑定,它应该可以从词法区域内到达,独立于包,我错了吗?
为什么要换包?我想在某些初始化点从swank加载这个文件会定义一些swank包中的东西,这就是为什么我想先尝试切换到cl-user,定义函数符号,然后切换回让swank做它的事情。
此时我想我需要有人告诉我,我正在从错误的角度解决问题,我最好选择一个更简单的解决方案。
此外,出于上述情况的好奇心是完全错误的方法,有没有办法在函数或闭包中的另一个包中定义符号?
答案 0 :(得分:8)
在表单中切换包对表单没有直接影响
让我们来看看:
(in-package "FOO")
(let ((x 10))
(in-package "BAR")
(setf x 20))
哪个x
设置为20? FOO::X
或BAR::X
?
嗯,它是FOO::X
。在执行期间切换包对已读取的符号没有影响。立即读取整个let
表单,并使用*package*
值。表单中有IN-PACKAGE
本身对表单本身没有影响。
带有包前缀的符号
如果要在某个包中使用符号,只需编写包前缀:
cl-user:foo ; if FOO is exported and the package exists
或
cl-user::foo ; if foo is not exported and the package exists
例如:
(defun cl-user::cd (...) ...)
使用符号进行计算
您还可以在尚不知道的包中计算新符号:
(let ((sym-name "A-NEW-SYMBOL")
(my-package-name "SOME-EXISTING-PACKAGE"))
(intern sym-name my-package-name))
如果包不存在,您可以创建它。
您还可以设置计算符号的功能:
(setf (symbol-function (compute-a-function-symbol))
#'(lambda ()
'foo))
答案 1 :(得分:4)
如果要在不同的包中定义当前的函数,可以使用限定符号作为名称
(defun cl-user::cd (dir)
(swank:set-default-directory
(parse-namestring dir)))
绑定不会“丢失”。要进行测试,请自行在包装内添加(princ cur-pck)
。
如果您尝试评估(in-package *package*)
,您将看到代码无法切换包的原因。包内宏不评估其参数。将为我们提供我们想要评估的代码的代码是:
(let ((cur-pck *package*))
(in-package :cl-user)
(defun cd (dir)
(swank:set-default-directory
(1+ 2)))
(princ cur-pck)
`(in-package ,cur-pck))
然而,正如Rainer Joswig在回答中指出的那样,包装内容对已阅读的表格没有任何影响,因此即使作为一个宏,它也无法正常工作。
样式挑剔,不要使用缩写,写当前包。
答案 2 :(得分:2)
IN-PACKAGE
是一个宏,而不是一个函数。您的代码中的问题是,(in-package cur-pck)
尝试不切换到cur-pck
变量表示的包,而是切换到名为CUR-PCK
的包(显然不存在)。
您可以使用
临时设置包(let ((*package* (find-package :cl-user)))
(defun cd (dir)
...))
然而,再一次,实现你所做的最简单的方法是
(defun cl-user::cd (dir)
...)
完全消除了设置当前包的需要。