【发布时间】:2019-03-11 10:24:52
【问题描述】:
我有下面的 Javascript 代码。 Common Lisp 中的等价物是什么?
function A () {
}
function B () {
}
var a1 = new A();
var b1 = new B();
a1.done.bind(b1);
我想做什么?我需要为将要执行的函数传递一个上下文(我在上下文中的意思是let 创建的,变量的绑定)。
我有一个函数 x1 和一个 x2,我希望它们能够访问 let 的变量。问题是我需要将函数作为变量传递。请参阅下面的尝试:
(defmacro create-context (vars &body body)
`(let ,vars
,@body))
(create-context ((x 2) (y 3)) (+ x y))
(defmacro create-suite-context (vars fn)
(with-gensyms (childs)
`(let ((,childs '()))
(create-context
,vars
(push ,fn ,childs)))))
(let* ((a (create-suite-context ((x 2)) (lambda () (+ x 1)))))
(funcall (car a)))
;; return 3 - OK
(let* ((f (lambda () (+ x 1)))
(a (create-suite-context ((x 2)) f)))
(funcall (car a)))
;; The variable X is unbound.
我明白为什么找不到 x,这是因为:
(let ((f (lambda () (+ x 1))))
(macroexpand-1 '(create-suite-context
((x 2))
f)))
; in: LET ((F (LAMBDA () (+ X 1))))
; (LET ((F (LAMBDA () (+ X 1))))
; (MACROEXPAND-1 '(CREATE-SUITE-CONTEXT ((X 2)) F)))
;
; caught STYLE-WARNING:
; The variable F is defined but never used.
; in: LET ((F (LAMBDA () (+ X 1))))
; (+ X 1)
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 1 WARNING condition
; caught 1 STYLE-WARNING condition
(LET ((#:G591 'NIL))
(CREATE-CONTEXT ((X 2))
(PUSH F #:G591)))
T
与此不同的是:
(macroexpand-1 '(create-suite-context
((x 2))
(lambda () (+ x 1))))
(LET ((#:G592 'NIL))
(CREATE-CONTEXT ((X 2))
(PUSH (LAMBDA () (+ X 1)) #:G592)))
T
因此,我认为我需要一些“绑定”宏,我可以在其中传递“vars”变量,以便函数可以访问。
注意:我知道我不需要create-context 宏,因为它所做的let 已经做了,但它是为了更好地解释我所说的上下文。强>
@jkiiski 回复后向上
我想最初为我的测试框架支持两种不同类型的接口:
(set-ui-cacau 'new-tdd)
(suite :suite-1
(let ((x y z))
(test :test-1
(let ((actual nil))
(t-p t))
:timeout 50)
(test :test-2
(let ((actual nil))
(t-p t))
:timeout 70)))
(run-cacau :reporter 'min)
;; or
(set-ui-cacau 'classic)
(in-suite :suite-1
:timeout 30
:parent :root)
(test :test-1
(let ((actual nil))
(t-p actual))
:timeout 50)
(test :test-2
(let ((actual nil)
(expected 1))
(setf actual 1)
(eq-p actual expected))
:timeout 70)
(run-cacau :reporter 'min)
如您所见,第一个界面更容易处理,因为我有可用的绑定。在第二个接口中没有办法做到这一点,我也可以用 let 包装,但这会带走我也选择实现这个接口的原因,即避免嵌套,这取决于我喜欢阅读的测试在第二个界面。所以这就是我提出这个问题的原因,真正的问题是如何在不使用显式 let 的情况下将上下文从 suite-1 传递到 test-1 和 test-2。
【问题讨论】:
标签: binding common-lisp let