为了解决我在使用Common时遇到的一些问题,我浏览了一下网络并发现:Variable references in lisp与我的问题非常相关。
阅读本部分:
认为有效!.因此,要做您想做的事情,代码需要( a)在作用域中,或者( b)可以访问作用域中的函数。
我想弄明白,但事情还不清楚。
首先,我不知道最后一句中所指的是什么( a)和b)。
第二,如何实际使用所提供的两段代码来获得所需的结果?
谢谢您提供的任何相关建议。
发布于 2017-06-15 07:15:16
我仍然不知道您在问什么问题,但是我想您想知道如何在无法看到绑定的函数范围内修改绑定。下面是这个问题的答案。
首先要理解的是,现代编程语言中的范围非常简单:如果您可以看到绑定(名称和值之间的关联),那么您可以访问它,如果它是可变的,则可以对其进行变异。以前的现代编程语言有各种各样的神秘规则,这些规则限制了这一点,因为很久以前,在微型计算机上实现起来很容易(我们都被PDP-11的遗产所诅咒),但是现代的编程语言把这一切都扫除了。从这个意义上讲,通用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的绑定是通过调用捕获它的函数来修改的。
但这在语法上是笨拙的:如果我们能够避免所有这些显式的funcalls和lambdas (我们可以在Lisp-1中避免前者,但仍然不是很好),那就太好了。因此,这里有一些代码可以做到这一点(下面解释一下):
(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)好的,所以宏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)))我认为这显然比上面所有的显式funcalls和lambdas更好阅读。它的工作方式也是一样的:
CL-USER 6 > (foo 1 2)
initially 1
then 2
2顺便说一句,只要setf知道如何处理它们(只要它们被称为“places”),您就可以捕获高速公路,而不仅仅是变量绑定:
(defun fish (l)
(bone (capture (car l)))
l)
(defun bone (c)
(setf (captured c) 'bone))而现在
CL-USER 13 > (fish (list 1 2))
(bone 2)https://stackoverflow.com/questions/44557821
复制相似问题