在球拍中, begin 不会创建新范围。 1 这意味着你在一个内部定义的任何东西 begin 表单仍在该表单之外的范围内。它还意味着begin不会更改上下文,因此如果您在表达式上下文中, begin 保持这一点。
begin
该 define 表格有(大致)以下语法:
define
(define <id> <expr>)
哪里 <id> 是变量名称,和 <expr> 是一种表达。然而 define 形式本身就是 不 表达式,所以这样的东西是无效的:
<id>
<expr>
(define x (define y 5))
因为begin不会改变上下文,所以这也是无效的:
(define x (begin (define y 5) y))
相反,你可以使用 let 创建一个新的范围。因为让它自己是一个表达式,你可以把它放在define中。所以你可以这样写:
let
(define x (let () (define y 5) y))
现在, x 一定会 5 正如所料。
x
5
回到原来的问题,你有代码:
518 ;; Qt-esque connect macro 519 (define-syntax connect-message 520 (syntax-rules () 521 [(register src-obj-key msg-type dst-obj-key handler) 522 (register-message-handler 523 msg-type 524 (begin 525 (define-coroutine 526 (handler-accessor) 527 (if (eqv? (get-dp-data-object dst-obj-key) #f) 528 #f 529 (send 530 (get-dp-data-object dst-obj-key) 531 handler 532 (get-field args msg)))) 533 handler-accessor))]))
我在假设 register-message-handler 是一个函数,因此需要一个表达式。但是你有 define-coroutine ,谁的阐述是一个 define 形成。所以而不是使用 begin ,你可以用一个 let 把它变成一个表达式,给你这样的东西:
register-message-handler
define-coroutine
(register-message-handler msg-type (let () (define-coroutine (handler-accessor) ....) handler-accessor))
<子> 1 糟糕的设计决定......我知道。从几十年前的桥下浇水。 :( 子>