Syntax 访问、实例化和声明模块之间有什么区别?
racket中的函数,如和,希望声明它们的模块,但不一定要访问或实例化 现在,对于如何需要模块,似乎有几个选项,包括访问和实例化Syntax 访问、实例化和声明模块之间有什么区别?,syntax,module,macros,racket,Syntax,Module,Macros,Racket,racket中的函数,如和,希望声明它们的模块,但不一定要访问或实例化 现在,对于如何需要模块,似乎有几个选项,包括访问和实例化 这让我想知道,声明一个模块、访问一个模块和实例化一个模块之间有什么区别?声明一个模块只是因为这个模块位于当前名称空间的某个地方。这既可以通过一个require来完成,也可以直接用代码写出模块 模块访问和实例化更难理解,最好这样描述: 模块访问正在运行阶段级别1(宏/编译时代码),而不是运行阶段级别0(运行时代码) 模块实例化正在运行阶段级别0代码,但不是阶段级别1代码
这让我想知道,声明一个模块、访问一个模块和实例化一个模块之间有什么区别?声明一个模块只是因为这个模块位于当前名称空间的某个地方。这既可以通过一个require来完成,也可以直接用代码写出模块 模块访问和实例化更难理解,最好这样描述:
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")))
#lang racket
(dynamic-require "test.rkt" #f)
此模块具有在阶段0、阶段1和阶段2(宏扩展阶段的宏扩展)运行的代码。在这些阶段中的每一个阶段,它都打印出一行,以指示该阶段正在运行。使用这个模块,我们可以看到模块何时被实例化
现在,让我们创建以下文件来实例化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")))
#lang racket
(dynamic-require "test.rkt" #f)
如果我们在DrRacket中运行此命令,输出将如下所示:
phase 2
phase 1
phase 0
现在,我们看到阶段0
,因为模块正在实例化。然而,在本例中,我们还可以看到阶段2
和阶段1
,因为模块的语法阶段必须实例化以运行阶段0
代码
但是,如果再次运行它(假设已打开已编译文件的缓存),您将获得:
phase 0
phase 2
phase 1
在这种情况下,您只能看到阶段0
,因为阶段1
和更高的代码已经展开。我们还可以为类似结果的动态需求提供0
现在,如果我们没有将0
或#f
传递到动态要求
,而是传递了(void)
,提供了以下文件:
#lang racket
(dynamic-require "test.rkt" (void))
然后输出将是(同样,假设已启用编译缓存),如下所示:
phase 1
这是因为宏级别(阶段1)代码在此处运行,而不是运行时(阶段0)代码。虽然如果我们对test.rkt做一点小小的更改并再次保存它(使缓存无效),我们将得到:
phase 0
phase 2
phase 1
这是因为Racket必须扩展阶段2
代码才能运行阶段1
代码。现在,已编译的模块缓存已更新,如果再次运行,它将仅输出:
phase 1
最后,没有任何方法可以直接使用dynamic require
来保证运行高于阶段级别1的代码(据我所知,如果我错了,请更新)