首页 > 解决方案 > 我应该为我的 Guile 项目中的每个文件定义单独的模块吗?

问题描述

让我通过比较来解释我的问题。在 Common Lisp 中,我可以将包定义拆分为多个文件,在每个文件中声明它in-packageload它们就足够了。

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

标签: moduleschemeguile

解决方案


事实上,在 Guile 中,您可以load在 a中define-module,但它会在编译时报告未绑定的变量。

惯用的方式是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并不普遍。这是依赖于define-module导入和导出的 GNU Guix 项目的示例:

(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

...

前缀语法也比等效的 using 更容易理解use-modules。这灵感来自 R6RSlibrary形式和 R7RSdefine-library形式。我不建议library在 Guile 中使用表单,因为它不能正确报告行。

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

您可以替换load为,include但我从未在 Guile 中使用过它


推荐阅读