Lisp 变量在定义中使用自身
Lisp variable using itself in definition
我正在使用 LTK 库在 Lisp 中构建一个 window 应用程序。我想要一个执行操作并可能隐藏自身的按钮。但是,这段代码:
(let* ((left (button 0 0 f "←" #'(lambda ()
(decf start page-length)
(funcall redraw)
(if (>= start page-length)
(ltk:configure left :state :visible))
(ltk:configure left :state :hidden))))))
声称“left”是一个未定义的变量(其余的在代码中定义超出了这个问题的范围)。
最坏的情况是,我避免使用我编写的“按钮”功能并针对这种特定情况重新编写代码,但这种情况需要一个通用的解决方案。 Lisp有没有办法在变量的定义中使用函数中的变量?
只有一个绑定的 let*
与 let
绑定相同。在执行正文之前,let
绑定不存在。在执行 button
期间,对 left
的引用必须来自较早的闭包或全局,因为 left
是在计算表达式后创建的。你可以这样做:
(let ((left nil))
(setf left (button 0 0 f "←" #'(lambda ()
(decf start page-length)
(funcall redraw)
(if (>= start page-length)
(ltk:configure left :state :visible)
(ltk:configure left :state :hidden))))))
注意:if
中存在错误,导致 lambda 始终执行 (ltk:configure left :state :hidden)
这里的价值是 CL 中 letrec
的一个版本:
(defmacro letrec (bindings &body decls/forms)
(assert (and (listp bindings)
(every (lambda (b)
(or (symbolp b)
(and (consp b)
(symbolp (first b))
(null (cddr b)))))
bindings))
(bindings) "malformed bindings")
(multiple-value-bind (names values)
(loop for b in bindings
collect (etypecase b
(symbol b)
(cons (first b)))
into vars
collect (etypecase b
(symbol nil)
(cons (second b)))
into vals
finally (return (values vars vals)))
`(let ,names
(psetf ,@(loop for name in names
for val in values
collect name
collect val))
(locally
,@decls/forms))))
然后
> (letrec ((x (lambda (y)
(if (null y)
'done
(funcall x (cdr y))))))
(funcall x '(1 2 3)))
done
我正在使用 LTK 库在 Lisp 中构建一个 window 应用程序。我想要一个执行操作并可能隐藏自身的按钮。但是,这段代码:
(let* ((left (button 0 0 f "←" #'(lambda ()
(decf start page-length)
(funcall redraw)
(if (>= start page-length)
(ltk:configure left :state :visible))
(ltk:configure left :state :hidden))))))
声称“left”是一个未定义的变量(其余的在代码中定义超出了这个问题的范围)。
最坏的情况是,我避免使用我编写的“按钮”功能并针对这种特定情况重新编写代码,但这种情况需要一个通用的解决方案。 Lisp有没有办法在变量的定义中使用函数中的变量?
只有一个绑定的 let*
与 let
绑定相同。在执行正文之前,let
绑定不存在。在执行 button
期间,对 left
的引用必须来自较早的闭包或全局,因为 left
是在计算表达式后创建的。你可以这样做:
(let ((left nil))
(setf left (button 0 0 f "←" #'(lambda ()
(decf start page-length)
(funcall redraw)
(if (>= start page-length)
(ltk:configure left :state :visible)
(ltk:configure left :state :hidden))))))
注意:if
中存在错误,导致 lambda 始终执行 (ltk:configure left :state :hidden)
这里的价值是 CL 中 letrec
的一个版本:
(defmacro letrec (bindings &body decls/forms)
(assert (and (listp bindings)
(every (lambda (b)
(or (symbolp b)
(and (consp b)
(symbolp (first b))
(null (cddr b)))))
bindings))
(bindings) "malformed bindings")
(multiple-value-bind (names values)
(loop for b in bindings
collect (etypecase b
(symbol b)
(cons (first b)))
into vars
collect (etypecase b
(symbol nil)
(cons (second b)))
into vals
finally (return (values vars vals)))
`(let ,names
(psetf ,@(loop for name in names
for val in values
collect name
collect val))
(locally
,@decls/forms))))
然后
> (letrec ((x (lambda (y)
(if (null y)
'done
(funcall x (cdr y))))))
(funcall x '(1 2 3)))
done