为了解决我在使用Common Lisp时遇到的一些问题,我浏览了网络并发现: Variable references in lisp 这与我的问题非常相关。Lisp /参数传递
阅读这一部分:
想想功能! .................. 因此,要做你想做的事,代码需要a)在范围内或b)可以访问范围内的函数。
我想弄清楚它,但事情并不清楚。
首先,我不确定a)和b)在最后一句中指的是什么。
第二我如何实际上使用提供的两个代码块来获得所需的结果?
在此先感谢您的任何相关提示。
为了解决我在使用Common Lisp时遇到的一些问题,我浏览了网络并发现: Variable references in lisp 这与我的问题非常相关。Lisp /参数传递
阅读这一部分:
想想功能! .................. 因此,要做你想做的事,代码需要a)在范围内或b)可以访问范围内的函数。
我想弄清楚它,但事情并不清楚。
首先,我不确定a)和b)在最后一句中指的是什么。
第二我如何实际上使用提供的两个代码块来获得所需的结果?
在此先感谢您的任何相关提示。
我仍然无法弄清楚你问的是什么问题,但我想你想知道如何在功能中的一个范围内修改绑定,而这个功能看不到绑定。所以这是对这个问题的回答。
首先要理解的是,现代编程语言中的范围非常简单:如果您可以看到绑定(名称和值之间的关联),那么您可以访问该绑定,并且如果它是可变的,则可以进行变异它。早期的现代编程语言有许多神秘的规则,这些规则基于很久以前在小型计算机上的易用性(我们都被PDP-11的遗留问题所诅咒),但是现代的编程语言扫除了所有这些。在这个意义上,Common Lisp大多是一种现代编程语言。
因此,您需要做的是以某种方式捕获绑定,然后将捕获的绑定传递给您要调用的任何函数,以便在其中进行访问或变异。捕获绑定的方式是使用函数。
所以,在这里是如何做到这一点的CL一个简单的例子:
(defun foo (orig new)
(let ((x orig))
(bar (lambda (&optional (value nil valuep))
(if valuep
(setf x value)
x))
new)
x))
(defun bar (c new)
(format t "~&initially ~S~%" (funcall c))
(funcall c new)
(format t "~&then ~S~%" (funcall c)))
在这段代码被第一个参数创建bar
功能访问的x
的结合,并且是这么写的所以不带任何参数调用它将返回绑定的值,而用参数调用它将设置值。下面是在行动:
CL-USER 5 > (foo 1 2)
initially 1
then 2
2
所以你可以看到这个作品:的x
绑定是通过调用其捕获它的功能修改。我们可以避免所有这些显式的funcall
s和lambda
s(我们可以避免前者在Lisp-1中,但它仍然不是很好)。但是,这在语法上很笨拙:如果我们可以避免所有这些显式的funcall
s和lambda
s因此,这里的一些代码做(它的解释如下)认为:
(defmacro capture (binding)
"Capture a binding"
(let ((value (make-symbol "VALUE"))
(valuep (make-symbol "VALUEP")))
`(lambda (&optional (,value nil ,valuep))
(if ,valuep
(setf ,binding ,value)
,binding))))
(defun captured (c &optional (value nil valuep))
"Return the value of a captured binding, or set it"
(if valuep
(funcall c value)
(funcall c)))
(defsetf captured captured)
OK,所以宏观capture
只是语法糖它创建等同于一个原代码的功能。它必须是一个宏,因为该功能需要在它捕获的绑定范围内创建。
captured
是那么平凡函数刚刚调用由capture
以适当的方式建立的功能:所以与其说(funcall c)
我们可以说(captured c)
。
最后defsetf
窗体教setf
如何设置捕获的绑定,所以(setf (captured x) y)
将工作。
这里是其使用上述foo
和bar
功能重新实现:
(defun foo (orig new)
(let ((x orig))
(bar (capture x) new)
x))
(defun bar (c new)
(format t "~&initially ~S~%" (captured c))
(setf (captured c) new)
(format t "~&then ~S~%" (captured c)))
我认为这是明显的,这是更好的比所有明确funcall
S和lambda
S上方阅读。它的工作方式相同:
CL-USER 6 > (foo 1 2)
initially 1
then 2
2
顺便说一句,你可以捕捉expresssions,不只是变量绑定,当然,只要setf
知道该怎么跟他们做的(只要它们是什么呼叫 '地方'):
(defun fish (l)
(bone (capture (car l)))
l)
(defun bone (c)
(setf (captured c) 'bone))
现在
CL-USER 13 > (fish (list 1 2))
(bone 2)
什么是 '期望的结果'?事实上,你问什么问题? – tfb
基本上,您只能通过调用关闭一组变量(或变异字段,数组)的闭包来直接(范围)或间接地设置您有权访问的变量。阅读http://www.gigamonkeys.com/book/variables.html – coredump