Racket中的函数(例如module->language-info
、module->imports
和module->exports
)需要声明其所在的模块,但不一定需要访问或实例化该模块。
现在,dynamic-require
似乎有几个选项可以用于要求模块,包括访问和实例化。
这使我想知道,声明模块、访问模块和实例化模块之间有什么区别?
Racket中的函数(例如module->language-info
、module->imports
和module->exports
)需要声明其所在的模块,但不一定需要访问或实例化该模块。
现在,dynamic-require
似乎有几个选项可以用于要求模块,包括访问和实例化。
这使我想知道,声明模块、访问模块和实例化模块之间有什么区别?
#lang racket
(require (for-meta 2 racket/base))
(displayln "phase 0")
(begin-for-syntax
(displayln "phase 1")
(begin-for-syntax
(displayln "phase 2")))
这个模块在0、1和2阶段运行代码(用于宏展开的宏展开阶段)。在每个阶段,它会打印一行以指示该阶段正在运行。使用此模块,我们可以看到模块何时被实例化。
现在,让我们创建以下文件来实例化test.rkt
:
#lang racket
(dynamic-require "test.rkt" #f)
phase 2
phase 1
phase 0
阶段0
,因为模块正在实例化。但是,在这种情况下,我们还会看到阶段2
和阶段1
,因为该模块的语法阶段必须被实例化以运行阶段0
代码。phase 0
phase 0
,因为phase 1
和更高版本的代码已经被展开。我们也可以将0
传递给动态要求以获得类似的结果。0
或#f
传递给dynamic-require
,而是传递(void)
,则会得到以下文件:#lang racket
(dynamic-require "test.rkt" (void))
phase 1
test.rkt
做出微小更改并再次保存(以使缓存失效),我们将会得到:phase 2
phase 1
第二阶段
代码才能运行第一阶段
代码。现在已经更新了编译后的模块缓存,如果再次运行它,它将只输出:phase 1
最后,据我所知(如果我错了,请更新),没有直接使用dynamic-require
来确保高于1级的阶段代码将被运行的方法。
(void)
传递给dynamic-require
函数。 - Nate