Common lisp 我可以通过它在函数名称空间中定义函数吗';s值多少?
我最近开始学习CL,我试图弄清楚是否可以在函数名称空间中为符号设置一个值 我只想根据函数组合定义函数,或者简单地通过现有函数定义函数(例如,在一个玩具“Hello,World!”级别的项目中,我只需重写Common lisp 我可以通过它在函数名称空间中定义函数吗';s值多少?,common-lisp,Common Lisp,我最近开始学习CL,我试图弄清楚是否可以在函数名称空间中为符号设置一个值 我只想根据函数组合定义函数,或者简单地通过现有函数定义函数(例如,在一个玩具“Hello,World!”级别的项目中,我只需重写identity两次)。我不确定这是否可能,因为它可能会打破名称空间分离(至少在没有强制的情况下)。我还尝试了macro扩展defun的实际功能;作为初学者,它对我来说太神秘了,但它的核心部分似乎是内置的(我正在使用SBCL) 因此,例如,不要说: (defun myfn (x) x) 我宁愿说
identity
两次)。我不确定这是否可能,因为它可能会打破名称空间分离(至少在没有强制的情况下)。我还尝试了macro扩展defun
的实际功能;作为初学者,它对我来说太神秘了,但它的核心部分似乎是内置的(我正在使用SBCL)
因此,例如,不要说:
(defun myfn (x) x)
我宁愿说:
(def..? myfn identity)
如果我不能做到这一点,如何避免此类代码重复?(包括通过函数组合创建的函数,而不仅仅是创建同义词)。在当前环境中,对于绑定到符号的函数,这是可能的:
还有(setf fdefinition)
,其功能大致相同,但也支持setf
功能
对于词汇绑定函数(通过FLET
和LABELS
)不能这样做
如何使用(setf fdefinition)
设置符号函数的示例
CL-USER 11 > (setf (fdefinition 'myfn) #'identity)
#<Function IDENTITY 410003F974>
CL-USER 12 > (myfn 10)
10
可能会被类似于
(eval-when (:compile-toplevel :load-toplevel :execute)
(setf (fdefinition 'myfn) #'identity))
优点:在编译过程中,该函数将像往常一样为人所知
要记住的一件事是:
符号对象可能携带一些信息。例如,原始函数名,如果有:
CL-USER 13 > #'identity
#<Function IDENTITY 410003F974>
自递归函数也有一个问题:
CL-USER 19 > (defun foo (n)
(if (zerop n)
1
(* n (foo (1- n))))) ; here foo calls the function foo
FOO
现在,我们将BAR
设置为使用函数FOO
CL-USER 20 > (setf (symbol-function 'bar) #'foo)
#<interpreted function FOO 4060004084>
CL-USER 21 > (bar 10)
3628800
BAR
仍然使用旧的FOO
,它可以调用新的FOO
CL-USER 23 > (bar 10)
460
哎呀!我们更改了FOO,但它对BAR有奇怪的影响:第一次迭代是旧的FOO,下一次递归调用是新的FOO
BAR
和FOO
是同一功能的两个不同版本。但两者都调用函数FOO
,这可能是旧函数,也可能是新函数,具体取决于您如何解释或编译代码
CL-USER 24 > #'foo
#<interpreted function FOO 40600041F4>
CL-USER 25 > #'bar
#<interpreted function FOO 4060004084>
CL-USER 24>#'foo
#
CL-USER 25>#栏
#
这只是一个想法,您可以添加一个宏,扩展到(defun myfun(&rest args)(apply identity args))
。当然,在Lisp-1中,您可以只使用(定义myfn标识)
。一定要查看从副本链接的一些函数。到处都是有用的信息。题为为什么defun与(setq)不一样?有一些很好的讨论。另外,为了清楚起见,您可以使用#“
表示法获得符号的函数值。也就是说,您不需要执行(let((id(lambda(x)x)))(compose id…)
。你可以只做(让((id#'identity))(编写id…)
或(编写#'identity…)
。
CL-USER 19 > (defun foo (n)
(if (zerop n)
1
(* n (foo (1- n))))) ; here foo calls the function foo
FOO
CL-USER 20 > (setf (symbol-function 'bar) #'foo)
#<interpreted function FOO 4060004084>
CL-USER 21 > (bar 10)
3628800
CL-USER 22 > (defun foo (n)
(if (zerop n)
1
(+ n (foo (1- n)))))
FOO
CL-USER 23 > (bar 10)
460
CL-USER 24 > #'foo
#<interpreted function FOO 40600041F4>
CL-USER 25 > #'bar
#<interpreted function FOO 4060004084>