【问题标题】:Can I instantiate a module multiple times in one Racket program?我可以在一个 Racket 程序中多次实例化一个模块吗?
【发布时间】:2016-11-03 00:07:00
【问题描述】:

假设我有一个名为 my-mod.rkt 的文件。

#lang racket ;; my-mod.rkt
(displayln "Module ran")

我显然可以通过在 repl 或其他脚本中实例化模块来运行此文件:

(require "my-mod.rkt")

打印出Module ran

但是,如果我不能以这种方式运行该模块两次。例如,如果我需要my-mod.rkt 两次:

(require "my-mod.rkt")
(require "my-mod.rkt")

模块只被实例化一次。这通常是你想要的,但在这种情况下,实例化模块有一个副作用,我想保留。

显然我可以使用find-exe 在另一个子进程中运行它:

(require compiler/find-exe)
(system* (find-exe) "my-mod.rkt")

然后我在另一个操作系统级别的进程中运行这个程序,这不是我想要做的。

那么,我可以在同一个 Racket 程序中两次实例化一个模块吗?

【问题讨论】:

    标签: module racket


    【解决方案1】:

    是的,你可以在同一个程序中两次实例化一个 Racket 模块。您可以通过更改您的current-namespace 并使用namespace-require 来做到这一点。

    例如,以下程序将需要 my-mod.rkt 模块两次:

    #lang racket
    (define ns (current-namespace))
    (parameterize ([current-namespace (make-base-namespace)])
      (namespace-require "my-mod.rkt"))
    
    (parameterize ([current-namespace (make-base-namespace)])
      (namespace-require "my-mod.rkt"))
    

    运行这个程序会打印出Module ran两次:

    Module ran
    Module ran
    

    请注意,您是在两个单独的命名空间中执行此操作的,因此从模块导入的任何内容在这两种情况下都会有所不同。如果您使用 namespace-attach-module 将模块从一个命名空间移动到另一个命名空间,您很可能会遇到此问题。

    另外请注意,由于您使用current-namespace 更改命名空间,您在当前模块中声明的任何子模块都将不再可见。这只适用于my-mod.rkt在另一个文件中,如果它是一个子模组,你将无法做到这一点。

    【讨论】: