首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >访问、实例化和声明模块之间有什么区别?

访问、实例化和声明模块之间有什么区别?
EN

Stack Overflow用户
提问于 2016-05-20 01:42:08
回答 1查看 67关注 0票数 3

racket中的函数(如module->language-infomodule->importsmodule->exports )期望声明它们的模块,但不一定要访问或实例化它们。

现在,dynamic-require似乎有几个关于如何要求模块的选项,包括访问和实例化。

这让我想知道,声明模块、访问模块和实例化模块有什么区别?

EN

Stack Overflow用户

回答已采纳

发布于 2016-05-20 02:07:47

声明一个模块只是因为该模块位于当前命名空间的某个位置。这既可以通过需求完成,也可以直接用代码写出模块。

模块访问和实例化更难理解,最好这样描述:

  1. 模块访问是运行阶段级别1(宏/编译时代码),而不是运行阶段级别0(运行时代码)。
  2. 模块实例化正在运行阶段级别0代码,但不运行阶段级别1代码。

现在,棘手的一点是,要运行阶段级0代码,必须先运行所有较高级别的分阶段代码,如果没有编译它。但是,如果该模块已经被访问(并编译),它将不会再次运行阶段1代码。

这可以从以下模块(称为test.rkt )中看到

代码语言:javascript
运行
复制
#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

代码语言:javascript
运行
复制
#lang racket
(dynamic-require "test.rkt" #f)

如果我们在DrRacket中运行它,输出将类似于:

代码语言:javascript
运行
复制
phase 2
phase 1
phase 0

现在,我们看到了phase 0,因为该模块正在实例化。然而,在本例中,我们也看到了phase 2phase 1,因为模块的语法阶段必须实例化才能运行phase 0代码。

但是,如果您再次运行它(假设您已打开已编译文件的缓存),您将得到:

代码语言:javascript
运行
复制
phase 0

在本例中,您只看到phase 0,因为phase 1和更高的代码已经展开。我们还可以给0提供类似结果的动态要求。

现在,如果我们没有将0#f传递给dynamic-require,而是传入了(void),给出了以下文件:

代码语言:javascript
运行
复制
#lang racket
(dynamic-require "test.rkt" (void))

然后输出(同样,假设您打开了编译缓存),如下所示:

代码语言:javascript
运行
复制
phase 1

这是因为宏级别(阶段1)代码正在这里运行,而不是运行时(阶段0)代码。虽然如果我们对test.rkt做了轻微的更改并再次保存它(以使缓存失效),但是我们将得到:

代码语言:javascript
运行
复制
phase 2
phase 1

这是因为Racket必须展开phase 2代码才能运行phase 1代码。既然编译后的模块缓存已经更新,如果再次运行它,它将只输出:

代码语言:javascript
运行
复制
phase 1

最后,没有(据我所见,如果我错了,请更新这一点),任何直接使用dynamic-require来保证运行高于阶段级别1的代码的方法。

票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37336657

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档