球拍中的功能,如module->language-info
,module->imports
和module->exports
希望他们的模块被声明,但不一定被访问或实例化。访问,实例化和声明模块有什么区别?
现在,dynamic-require
似乎有几个选择如何需要模块,包括访问和实例化。
这让我想知道,声明模块,访问模块和实例化模块有什么区别?
球拍中的功能,如module->language-info
,module->imports
和module->exports
希望他们的模块被声明,但不一定被访问或实例化。访问,实例化和声明模块有什么区别?
现在,dynamic-require
似乎有几个选择如何需要模块,包括访问和实例化。
这让我想知道,声明模块,访问模块和实例化模块有什么区别?
声明一个模块就是这个模块在当前命名空间的某个地方。这可以通过一个需求来完成,或者直接在代码中写出模块。
模块访问并实例化是比较麻烦一些理解,并且可以被描述为这样:
模块来访运行阶段电平1(宏/编译时间码),并没有运行相级别0(运行时间代码)。
模块实例化运行相位0级代码,但不运行相位1级代码。现在
,棘手位,运行相平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
这是因为球拍不得不扩大phase 2
代码,以便能够运行phase 1
码。现在,编译的模块缓存已经更新,如果您再次运行它,它只会输出:
phase 1
最后,没有(据我所看到的,请更新这一点,如果我错了) ,任何直接使用dynamic-require
的方式都可以保证运行高于阶段1的代码。