我应该为我的 Guile 项目中的每个文件定义单独的模块吗?
Should I define separate module for every file in my Guile project?
我来对比一下我的问题。在 Common Lisp 中,我可以将包定义拆分为多个文件,在每个文件中声明它是 in-package
和 load
就足够了。
但是在 Guile Scheme 中,我似乎应该 define-module
,为每个文件分开?好吧,我仍然可以 load
一些文件,比如在 CL 中,它看起来像工作,define-modules
似乎不限于它所在的单个文件,就像在 CL 中一样,但我收到关于未定义名称的警告(那些在 load
ed 文件中定义),所以我觉得这不是 Guile 所期望的。有没有 (1) 像 CL 那样在多个文件中拆分模块的方法,或者 (2) 我应该坚持使用 use-module
自动加载功能并为每个文件单独使用 define-module
吗?
确实在 Guile 中你可以在 define-module
中 load
但它会在编译时报告未绑定变量。
惯用的方式是每个文件中的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
中使用过它
我来对比一下我的问题。在 Common Lisp 中,我可以将包定义拆分为多个文件,在每个文件中声明它是 in-package
和 load
就足够了。
但是在 Guile Scheme 中,我似乎应该 define-module
,为每个文件分开?好吧,我仍然可以 load
一些文件,比如在 CL 中,它看起来像工作,define-modules
似乎不限于它所在的单个文件,就像在 CL 中一样,但我收到关于未定义名称的警告(那些在 load
ed 文件中定义),所以我觉得这不是 Guile 所期望的。有没有 (1) 像 CL 那样在多个文件中拆分模块的方法,或者 (2) 我应该坚持使用 use-module
自动加载功能并为每个文件单独使用 define-module
吗?
确实在 Guile 中你可以在 define-module
中 load
但它会在编译时报告未绑定变量。
惯用的方式是每个文件中的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