Let me explain my problem by comparison. In Common Lisp I could split package definitions to several files, it was enough to declare in each of them that it's in-package
and load
them.
However in Guile Scheme it looks like I should define-module
, separate for each file? Well I still can load
some files like in CL and it looks like working, define-modules
seems not limited to a single file it is located in like in CL, but I get warnings about undefined names (those that are defined in load
ed files), so it gives me feeling that it's not what Guile expects. Is there (1) some way of splitting module across several files like in CL, or (2) should I stick to use-module
autoload feature and define-module
for each file separatelly?
Indeed in Guile you can load
inside a define-module
but it will report unbound variable at compile time.
The idiomatic way is the define-module
in every file:
;; 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
...
Then in earth-software-system/bullet-train.scm
you can have:
;; in earth-software-system/bullet-train.scm
(define-module (earth-software-system bullet-train))
(use-modules (srfi srfi-9))
(define-public bullet-train 42)
...
Mind the fact that define-public
and a single import per use-modules
is not widespread. Here is an example from GNU Guix project that rely on define-module
to import and export:
(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))
Also nowadays I prefer the import
form which is more easy to the mind that 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
...
The prefix syntax is also more easy to the mind than the equivalent using use-modules
. This is inspired from R6RS library
form and R7RS define-library
form. I do not recommend to use library
form in Guile since it doesn't report lines correctly.
GNU Guile allow to import forms even if they are not exported using the @@
syntax for instance to test some tricky behavior.
You might replace load
with include
but I never used it in Guile