ftl*_*ftl 3 namespaces eval racket
假设我有一个模块“ foo.rkt”,可导出结构foo,例如,
#lang racket (provide foo) (struct foo ())
Run Code Online (Sandbox Code Playgroud)
在另一个模块中,我使用“ foo.rkt”,但我也想将绑定到“ struct foo”关联到另一个名称空间(出于各种原因,我不使用预制,所以我不能使用名称空间要求) 。
我以为我可以按以下方式使用namespace-attach-module:
(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) "foo.rkt" ns)
(eval '(foo) ns)
Run Code Online (Sandbox Code Playgroud)
但这是行不通的,因为命名空间映射符号显示s在ns中没有绑定(如果这是查找绑定的唯一位置)。但是,它确实可以在REPL中使用。为什么?
我认为问题是避免在“ 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)
Run Code Online (Sandbox Code Playgroud)
文件:“ 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"
Run Code Online (Sandbox Code Playgroud)
运行此命令的结果是:
"Apple"
Run Code Online (Sandbox Code Playgroud)
请注意,删除该namespace-attach-module行会导致错误:
computer-name: contract violation;
given value instantiates a different structure type with the same name
expected: computer?
given: (computer "Apple" 2000)
Run Code Online (Sandbox Code Playgroud)
由于没有附件,namespace-require第二次将声明“ computer.rkt”无效,从而导致两个不兼容的结构开始声明。