我应该为我的 Guile 项目中的每个文件定义单独的模块吗?

Should I define separate module for every file in my Guile project?

我来对比一下我的问题。在 Common Lisp 中,我可以将包定义拆分为多个文件,在每个文件中声明它是 in-packageload 就足够了。

但是在 Guile Scheme 中,我似乎应该 define-module,为每个文件分开?好吧,我仍然可以 load 一些文件,比如在 CL 中,它看起来像工作,define-modules 似乎不限于它所在的单个文件,就像在 CL 中一样,但我收到关于未定义名称的警告(那些在 loaded 文件中定义),所以我觉得这不是 Guile 所期望的。有没有 (1) 像 CL 那样在多个文件中拆分模块的方法,或者 (2) 我应该坚持使用 use-module 自动加载功能并为每个文件单独使用 define-module 吗?

确实在 Guile 中你可以在 define-moduleload 但它会在编译时报告未绑定变量。

惯用的方式是每个文件中的define-module

;; in earth-software-system.scm
(define-module (earth-software-system))

(use-modules (earth-software-system bullet-train))
(use-modules (srfi srfi-9))

(re-export bullet-train) ;; possibly re-exporting imported bindings

...

那么在earth-software-system/bullet-train.scm你可以有:

;; in earth-software-system/bullet-train.scm
(define-module (earth-software-system bullet-train))

(use-modules (srfi srfi-9))

(define-public bullet-train 42)

...

请注意 define-public 和每个 use-modules 一次导入并不普遍。这是一个来自 GNU Guix 项目的例子,它依赖 define-module 导入和导出:

(define-module (guix cpio)
  #:use-module ((guix build utils) #:select (dump-port))
  #:use-module (srfi srfi-9)
  #:use-module (srfi srfi-11)
  #:use-module (rnrs bytevectors)
  #:use-module (rnrs io ports)
  #:use-module (ice-9 match)
  #:export (cpio-header?
            make-cpio-header
            file->cpio-header
            file->cpio-header*
            write-cpio-header
            read-cpio-header

            write-cpio-archive))

现在我更喜欢 import 形式,它比 use-modules:

更容易让人记住
;; in earth-software-system.scm
(define-module (earth-software-system))

(import (prefix (earth-software-system bullet-train) 'bt:)
(import (srfi srfi-9))

(re-export bt:bullet-train) ;; possibly re-exporting imported bindings

...

前缀语法也比使用 use-modules 的语法更容易理解。这是从 R6RS library 形式和 R7RS define-library 形式中得到启发。我不建议在 Guile 中使用 library 表单,因为它不能正确报告行。

GNU Guile 允许导入表单,即使它们没有导出,例如使用 @@ syntax 来测试一些棘手的行为。

您可以将 load 替换为 include,但我从未在 Guile

中使用过它