如何在 Racket 中获取自定义语言的命名空间?
How to obtain namespace of a custom lang in Racket?
我正在 Racket 中实现一种自定义语言,我想在其中提供一个绑定到该自定义语言的命名空间的 eval
过程。
我的-lang.rkt:
#lang racket
(provide #%module-begin #%top #%datum #%app)
(provide quote)
(provide (rename-out [a b] [my-eval eval]))
(define-namespace-anchor anchor)
(define ns (namespace-anchor->namespace anchor)) ; wrong namespace
(define (my-eval x) (eval x ns))
(define a 1)
test.rkt:
#lang s-exp "my-lang.rkt"
(eval 'a)
(eval 'b)
实施时,由于 ns
是 my-lang.rkt 的命名空间,(eval 'a)
计算为 1
而 (eval 'b)
失败。
我希望 ns
绑定到 test.rkt 的命名空间,以便 (eval 'a)
失败并且 (eval 'b)
returns 1
.
我该如何定义ns
?
这是一种使用参数和宏的方法。可能有更好的方法:
;; my-lang.rkt
#lang racket
(provide #%top #%datum #%app (rename-out [@#%module-begin #%module-begin])
quote
(rename-out [a b] [my-eval eval]))
(require syntax/parse/define
racket/splicing)
(define current-ns (make-parameter #f))
(define-syntax-parser @#%module-begin
[(_ . xs)
#'(#%module-begin
(define-namespace-anchor anchor)
(splicing-parameterize ([current-ns (namespace-anchor->namespace anchor)])
. xs))])
(define (my-eval x) (eval x (current-ns)))
(define a 1)
;; test.rkt
#lang s-exp "my-lang.rkt"
(eval 'b) ;=> 1
(eval 'a)
;; a: undefined;
;; cannot reference an identifier before its definition
我正在 Racket 中实现一种自定义语言,我想在其中提供一个绑定到该自定义语言的命名空间的 eval
过程。
我的-lang.rkt:
#lang racket
(provide #%module-begin #%top #%datum #%app)
(provide quote)
(provide (rename-out [a b] [my-eval eval]))
(define-namespace-anchor anchor)
(define ns (namespace-anchor->namespace anchor)) ; wrong namespace
(define (my-eval x) (eval x ns))
(define a 1)
test.rkt:
#lang s-exp "my-lang.rkt"
(eval 'a)
(eval 'b)
实施时,由于 ns
是 my-lang.rkt 的命名空间,(eval 'a)
计算为 1
而 (eval 'b)
失败。
我希望 ns
绑定到 test.rkt 的命名空间,以便 (eval 'a)
失败并且 (eval 'b)
returns 1
.
我该如何定义ns
?
这是一种使用参数和宏的方法。可能有更好的方法:
;; my-lang.rkt
#lang racket
(provide #%top #%datum #%app (rename-out [@#%module-begin #%module-begin])
quote
(rename-out [a b] [my-eval eval]))
(require syntax/parse/define
racket/splicing)
(define current-ns (make-parameter #f))
(define-syntax-parser @#%module-begin
[(_ . xs)
#'(#%module-begin
(define-namespace-anchor anchor)
(splicing-parameterize ([current-ns (namespace-anchor->namespace anchor)])
. xs))])
(define (my-eval x) (eval x (current-ns)))
(define a 1)
;; test.rkt
#lang s-exp "my-lang.rkt"
(eval 'b) ;=> 1
(eval 'a)
;; a: undefined;
;; cannot reference an identifier before its definition