我下面有Javascript代码。普通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的情况下将上下文从套件1传递到test-1和test-2。