爲了解決我在使用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