我现在已经坚持了几个小时的问题。我正在尝试使用Racket的语言扩展功能来定义DSL。我想做类似下面的伪代码。最后,我想在DSL中输入生成函数和宏,并且大多数现在似乎都可以工作,问题是提供的定义应该与声明处于同一级别。这甚至可能吗?现在已经晚了,我肯定我错过了一些非常微不足道的东西。问题的最基本的例子是:
tinylang.rkt:
#lang racket
; here we redefine module begin.
(provide (all-defined-out)
(except-out (all-from-out racket) #%module-begin)
(rename-out [module-begin #%module-begin])
)
(define-syntax (module-begin stx)
(syntax-case stx ()
[(_ stmts ...)
#`(#%module-begin
(define (hello) (print "Yes!") (newline))
; (provide (for-syntax hello))
(print "Function defined.")
stmts ... )]))
现在我尝试在其他地方使用这种新语言:
try.rkt:
#lang s-exp "tinylang.rkt"
(hello)
但是在加载第二个模块时,我收到错误“hello:模块中的未绑定标识符:hello”。
答案 0 :(得分:5)
问题在于hello
的词法范围中定义了tinylang.rkt
,但您希望它位于try.rkt
的范围内。您可以使用datum->syntax
设置一段语法的词汇上下文。
这将解决问题:
#lang racket
; here we redefine module begin.
(provide (all-defined-out)
(except-out (all-from-out racket) #%module-begin)
(rename-out [module-begin #%module-begin])
)
(define-syntax (module-begin stx)
(syntax-case stx ()
[(_ stmts ...)
#`(#%module-begin
#,(datum->syntax
stx
(syntax->datum
#'(define (hello) (print "Yes!") (newline))))
(print "Function defined.")
stmts ... )]))
更新:
在回应评论时,之前的解决方案可以简化为:
(define-syntax (module-begin stx)
(syntax-case stx ()
[(_ stmts ...)
(with-syntax ([hello-fn (datum->syntax stx 'hello)])
#`(#%module-begin
(define (hello-fn) (print "Yes!") (newline))
(print "Function defined.")
stmts ... ))]))