在 Racket 中需要 vs 加载 vs 包含 vs 导入
require vs load vs include vs import in Racket
Racket 文档表明 Racket 有单独的形式:require
, load
, include
, and import
。许多其他语言仅包含其中一种并且通常作为同义词使用(尽管明显存在语言特定差异,例如 C 中的 #include
和 Java 中的 import
)。
既然 Racket 有这四种,那么它们之间有什么区别,我通常应该使用哪一种?另外,如果每个都有特定用途,我应该什么时候使用替代类型?另外, seems to indicate that require
(paired with provide
) 是首选,为什么?
1。需要
你是对的,你想要的默认值几乎总是 require
(与 provide
配对)。这两种形式与 Racket 的 modules
齐头并进,使您可以更轻松地确定哪些变量应该在哪些文件中起作用。例如,下面的文件定义了三个变量,但只导出了 2 个。
#lang racket ; a.rkt
(provide b c)
(define a 1)
(define b 2)
(define c 3)
根据 the Racket style guide,provide 最好是文件中 #lang
之后的第一个表单,这样您就可以轻松分辨模块提供的内容。在某些情况下这是不可能的,但在您开始制作自己的 Racket 库并打算用于 public 分发之前,您可能不会遇到这些情况。就个人而言,我仍然将文件的 require
放在其 provide
之前,但有时我确实会因此而受到批评。
在 repl 或其他模块中,您现在可以要求此文件并查看它提供的变量。
Welcome to Racket v6.12.
> (require "a.rkt")
> c
3
> b
2
> a
; a: undefined;
; cannot reference undefined identifier
; [,bt for context]
有 ways to get around this,但这是模块传达其显式导出内容的一种方式。
2。加载
这是 require 的一个更动态的变体。一般来说你不应该使用它,而是使用 dynamic-require
when you need to load a module dynamically. In this case, load
is effectively a primitive that require
uses behind the scenes. If you are explicitly looking to emulate the top level however (which, to be clear, you almost never do), then load is a fine option. Although in those rare cases, I would still direct you to the racket/load
语言。其交互方式就好像每个表单都直接输入到 repl 中一样。
#lang racket/load
(define x 5)
(displayln x) ; => prints 5
(define x 6)
(displayln x) ; => prints 6
3。包括
Include 类似于 C 中的 #include
。应该使用它的情况更少。 include
形式获取给定路径的 s-expression 语法,并将其直接放入 include
形式所在的文件中。起初,这似乎是一个不错的解决方案,允许您将单个模块拆分为多个文件,或者将一个模块 'piece' 放入多个文件中。然而,有更好的方法可以在不使用 include
的情况下完成这两件事,这也不会带来 include 带来的令人困惑的副作用。1 需要记住的一件事如果您仍然坚持使用 import
,是因为您正在导入的文件可能不应该有 #lang
行,除非您明确想要嵌入子模块。 (在这种情况下,除了 include
之外,您还需要有一个 require
表格)。
4。导入
最后,import
实际上并不是Racket的核心部分,而是其unit system的一部分。单元在某些方面类似于模块,但允许循环依赖(单元 A 可以依赖单元 B,而单元 B 依赖单元 A)。近年来,由于它们的句法开销,它们已经失宠了。
与其他形式 import
(另外还有 export
)不同,采用 signatures, and relies on an external linker 来决定哪些实际单位应该 link 合并。单位本身就是一个复杂的话题,并且应该就如何创建和 link 提出自己的问题。
结论(tldr)
TLDR;使用 require
和 provide
。他们是最好的支持和最容易理解的。其他形式确实有它们的用途,但应该只考虑 'advanced uses'。
1这些副作用与你在 C 中对 #include
的预期相同。例如顺序很重要,还有表达式以非常不可预测的方式混合在一起。
Racket 文档表明 Racket 有单独的形式:require
, load
, include
, and import
。许多其他语言仅包含其中一种并且通常作为同义词使用(尽管明显存在语言特定差异,例如 C 中的 #include
和 Java 中的 import
)。
既然 Racket 有这四种,那么它们之间有什么区别,我通常应该使用哪一种?另外,如果每个都有特定用途,我应该什么时候使用替代类型?另外,require
(paired with provide
) 是首选,为什么?
1。需要
你是对的,你想要的默认值几乎总是 require
(与 provide
配对)。这两种形式与 Racket 的 modules
齐头并进,使您可以更轻松地确定哪些变量应该在哪些文件中起作用。例如,下面的文件定义了三个变量,但只导出了 2 个。
#lang racket ; a.rkt
(provide b c)
(define a 1)
(define b 2)
(define c 3)
根据 the Racket style guide,provide 最好是文件中 #lang
之后的第一个表单,这样您就可以轻松分辨模块提供的内容。在某些情况下这是不可能的,但在您开始制作自己的 Racket 库并打算用于 public 分发之前,您可能不会遇到这些情况。就个人而言,我仍然将文件的 require
放在其 provide
之前,但有时我确实会因此而受到批评。
在 repl 或其他模块中,您现在可以要求此文件并查看它提供的变量。
Welcome to Racket v6.12.
> (require "a.rkt")
> c
3
> b
2
> a
; a: undefined;
; cannot reference undefined identifier
; [,bt for context]
有 ways to get around this,但这是模块传达其显式导出内容的一种方式。
2。加载
这是 require 的一个更动态的变体。一般来说你不应该使用它,而是使用 dynamic-require
when you need to load a module dynamically. In this case, load
is effectively a primitive that require
uses behind the scenes. If you are explicitly looking to emulate the top level however (which, to be clear, you almost never do), then load is a fine option. Although in those rare cases, I would still direct you to the racket/load
语言。其交互方式就好像每个表单都直接输入到 repl 中一样。
#lang racket/load
(define x 5)
(displayln x) ; => prints 5
(define x 6)
(displayln x) ; => prints 6
3。包括
Include 类似于 C 中的 #include
。应该使用它的情况更少。 include
形式获取给定路径的 s-expression 语法,并将其直接放入 include
形式所在的文件中。起初,这似乎是一个不错的解决方案,允许您将单个模块拆分为多个文件,或者将一个模块 'piece' 放入多个文件中。然而,有更好的方法可以在不使用 include
的情况下完成这两件事,这也不会带来 include 带来的令人困惑的副作用。1 需要记住的一件事如果您仍然坚持使用 import
,是因为您正在导入的文件可能不应该有 #lang
行,除非您明确想要嵌入子模块。 (在这种情况下,除了 include
之外,您还需要有一个 require
表格)。
4。导入
最后,import
实际上并不是Racket的核心部分,而是其unit system的一部分。单元在某些方面类似于模块,但允许循环依赖(单元 A 可以依赖单元 B,而单元 B 依赖单元 A)。近年来,由于它们的句法开销,它们已经失宠了。
与其他形式 import
(另外还有 export
)不同,采用 signatures, and relies on an external linker 来决定哪些实际单位应该 link 合并。单位本身就是一个复杂的话题,并且应该就如何创建和 link 提出自己的问题。
结论(tldr)
TLDR;使用 require
和 provide
。他们是最好的支持和最容易理解的。其他形式确实有它们的用途,但应该只考虑 'advanced uses'。
1这些副作用与你在 C 中对 #include
的预期相同。例如顺序很重要,还有表达式以非常不可预测的方式混合在一起。