racket中的函数(如module->language-info、module->imports和module->exports )期望声明它们的模块,但不一定要访问或实例化它们。
现在,dynamic-require似乎有几个关于如何要求模块的选项,包括访问和实例化。
这让我想知道,声明模块、访问模块和实例化模块有什么区别?
发布于 2016-05-20 02:07:47
声明一个模块只是因为该模块位于当前命名空间的某个位置。这既可以通过需求完成,也可以直接用代码写出模块。
模块访问和实例化更难理解,最好这样描述:
现在,棘手的一点是,要运行阶段级0代码,必须先运行所有较高级别的分阶段代码,如果没有编译它。但是,如果该模块已经被访问(并编译),它将不会再次运行阶段1代码。
这可以从以下模块(称为test.rkt )中看到
#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)如果我们在DrRacket中运行它,输出将类似于:
phase 2
phase 1
phase 0现在,我们看到了phase 0,因为该模块正在实例化。然而,在本例中,我们也看到了phase 2和phase 1,因为模块的语法阶段必须实例化才能运行phase 0代码。
但是,如果您再次运行它(假设您已打开已编译文件的缓存),您将得到:
phase 0在本例中,您只看到phase 0,因为phase 1和更高的代码已经展开。我们还可以给0提供类似结果的动态要求。
现在,如果我们没有将0或#f传递给dynamic-require,而是传入了(void),给出了以下文件:
#lang racket
(dynamic-require "test.rkt" (void))然后输出(同样,假设您打开了编译缓存),如下所示:
phase 1这是因为宏级别(阶段1)代码正在这里运行,而不是运行时(阶段0)代码。虽然如果我们对test.rkt做了轻微的更改并再次保存它(以使缓存失效),但是我们将得到:
phase 2
phase 1这是因为Racket必须展开phase 2代码才能运行phase 1代码。既然编译后的模块缓存已经更新,如果再次运行它,它将只输出:
phase 1最后,没有(据我所见,如果我错了,请更新这一点),任何直接使用dynamic-require来保证运行高于阶段级别1的代码的方法。
https://stackoverflow.com/questions/37336657
复制相似问题