gpt4 book ai didi

scheme - 如何修复此 Scheme 协程代码以在 Racket 中运行

转载 作者:太空宇宙 更新时间:2023-11-03 18:51:32 26 4
gpt4 key购买 nike

我正在尝试使用来自 this accepted answer 的方案实现在 Racket LISP 中为个人学习项目实现协程。 .但是,当将我的 .rkt 文件加载到 Racket repl 时,出现以下错误:

; 3.rkt:111:18: define: not allowed in an expression context
; in: (define (run-handler) (make-generator (lambda (yield) (send
; (get-dp-data-object key) run))))

它似乎在提示这部分代码中的定义:

108 (define-syntax (define-coroutine stx)                                                               
109 (syntax-case stx ()
110 ((_ (name . args) . body )
111 #`(define (name . args)
112 (make-generator
113 (lambda (#,(datum->syntax stx 'yield))
114 . body))))))

根据accepted answer here这个确切的错误不被 Scheme 共享,并且在尝试在表达式中定义时是 Racket 独有的。

代码调用(define-coroutine)似乎是:

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))]))

这是我的第一个 Racket 项目,所以我正在学习很多。上面的 (begin) 试图定义并返回一个调用对象方法的协程。我确信这个代码片段有很多问题,但是调试器用上面的问题阻止了我,阻止我得到以后的错误:)

我在 Racket、Scheme 或 LISP 方面几乎不够熟练,无法解决这个问题,目前我很难理解这个错误。有人可以为我解决这个问题并希望纠正这个问题,这样我就可以让这个协程代码在 Racket 中工作吗?

最佳答案

在 Racket 中,begin不会创建新范围。1 这意味着您在 begin 中定义的任何内容表单仍在该表单之外的范围内。这也意味着 begin 不会改变上下文,所以如果你在表达式上下文中,begin保留那个。

define表单具有(大致)以下语法:

(define <id> <expr>)

在哪里<id>是变量名,<expr>是一个表达式。然而,define表单本身不是一个表达式,所以这样的东西是无效的:

(define x (define y 5))

因为 begin 不改变上下文,所以这也是无效的:

(define x
(begin
(define y 5)
y))

相反,您可以使用 let创建一个新的范围。而且因为let本身就是一个表达式,所以可以放在define中。所以你可以这样写:

(define x
(let ()
(define y 5)
y))

现在,x绑定(bind)到 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                                  
msg-type
(let ()
(define-coroutine (handler-accessor) ....)
handler-accessor))

1糟糕的设计决定……我知道。几十年前桥下的水。 :(

关于scheme - 如何修复此 Scheme 协程代码以在 Racket 中运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51690804/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com