如何在 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)

实施时,由于 nsmy-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