Racket:eval,namespace-attach-module与namespace-require

时间:2018-06-17 14:53:23

标签: namespaces racket eval

我们说我有一个模块" foo.rkt"它导出一个struct foo,例如,

#lang racket (provide foo) (struct foo ())

在另一个模块中,我使用" foo.rkt"但我也想将绑定与" struct foo"到另一个命名空间(由于各种原因,我不使用预制件,所以我不能使用命名空间 - )。

我认为我可以使用namespace-attach-module,如下所示:

(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) "foo.rkt" ns)
(eval '(foo) ns)

但这不起作用,因为名称空间映射符号显示s未绑定在ns中(如果这是查找绑定的唯一位置)。然而它确实在REPL中起作用。为什么呢?

1 个答案:

答案 0 :(得分:5)

我认为问题是要避免在" foo.rkt"中实例化模块。两次,因为这会导致两个不兼容的结构定义。

函数namespace-attach-module是谜题的一部分,但它只是附加 命名空间ns的实例化模块 - 即名称" foo.rkt"现在与" foo.rkt"的正确实例化相关联。然而,它并没有在ns中提供绑定 - 这是namespace-require的工作。

以下是一个例子:

文件:" computer.rkt"

#lang racket
(provide (struct-out computer))
(struct computer (name price) #:transparent)

文件:" use-computer.rkt"

#lang racket
(require "computer.rkt")                                        ; instatiate "computer.rkt"
(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) "computer.rkt" ns) ; ns now knows the same instance
(define a-computer
  (parameterize ([current-namespace ns])
    (namespace-require "computer.rkt") 
    (eval '(computer "Apple" 2000) ns)))    

(computer-name a-computer)  ; works, since ns used the same instantiation of "computer.rkt"

运行它的结果是:

"Apple"

请注意,删除namespace-attach-module行会导致错误:

computer-name: contract violation;
 given value instantiates a different structure type with the same name
  expected: computer?
  given: (computer "Apple" 2000)

由于没有附件,namespace-require将启动" computer.rkt"第二次开始宣布两个不兼容的结构。