在 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;使用 requireprovide。他们是最好的支持和最容易理解的。其他形式确实有它们的用途,但应该只考虑 'advanced uses'。

1这些副作用与你在 C 中对 #include 的预期相同。例如顺序很重要,还有表达式以非常不可预测的方式混合在一起。