Modules Guide
This guide covers the Sigil module system in depth.
Library Basics
Modules are defined with define-library:
(define-library (myapp utils)
(export helper-function another-function)
(begin
(define (helper-function x) ...)
(define (another-function y) ...)))Note: Basic Scheme forms (define, if, lambda, arithmetic, etc.) are available without imports. Use import to bring in additional modules like (sigil io) or (sigil string).
Library Names
Library names are lists of symbols that form a hierarchical namespace:
(sigil io) ; Standard library module
(myapp utils) ; Your application module
(myapp data models) ; Nested namespaceExports
Only explicitly exported bindings are visible to importers:
(export
public-procedure ; A procedure
*global-constant* ; A value
my-macro) ; A macroPrivate bindings remain internal:
(define-library (example)
(export public-fn)
(begin
(define (private-helper x) (* x 2))
(define (public-fn x) (private-helper (+ x 1)))))Import Forms
Basic Import
(import (myapp utils))All exports become available by their original names.
Selective Imports
Import only specific bindings:
(import (only (myapp utils)
helper-function))Import all except specific bindings:
(import (except (myapp utils)
deprecated-function))Renaming
Rename bindings to avoid conflicts or improve clarity:
(import (rename (myapp utils)
(helper-function util-helper)
(another-function util-other)))
(util-helper 42) ; Use the renamed bindingPrefixes
Add a prefix to all imported bindings:
(import (prefix (myapp utils) utils:))
(utils:helper-function 42)Combining Forms
Import forms can be combined:
(import (prefix
(only (myapp utils) helper-function)
u:))
(u:helper-function 42)File Organization
Mapping Names to Files
Library names map to file paths:
| Library Name | File Path |
|---|---|
(myapp utils) | myapp/utils.sgl |
(myapp data models) | myapp/data/models.sgl |
(sigil io) | sigil/io.sgl |
Search Path
Sigil searches for libraries in:
- Current directory
- Load path directories (set via environment or command line)
- Standard library location
Recommended Structure
my-project/
├── package.sgl ; Package metadata
├── src/
│ └── myapp/
│ ├── main.sgl ; Entry point
│ ├── core.sgl ; Core functionality
│ ├── utils.sgl ; Utilities
│ └── data/
│ ├── models.sgl ; Data models
│ └── storage.sgl ; Persistence
└── test/
├── test-core.sgl
└── test-utils.sglMultiple begin Blocks
A library can have multiple begin blocks for organization:
(define-library (myapp utils)
(export string-helpers list-helpers)
;; String utilities
(begin
(define (string-helpers ...) ...))
;; List utilities
(begin
(define (list-helpers ...) ...)))Conditional Code
Use cond-expand for platform-specific code:
(define-library (myapp platform)
(export get-home-directory)
(cond-expand
(linux
(begin
(define (get-home-directory)
(getenv "HOME"))))
(windows
(begin
(define (get-home-directory)
(getenv "USERPROFILE"))))
(else
(begin
(define (get-home-directory) #f)))))Re-exporting
Create facade modules that re-export from multiple sources:
(define-library (myapp)
(import (myapp core)
(myapp utils)
(myapp data))
(export
;; From core
initialize shutdown
;; From utils
helper-function
;; From data
save-data load-data))Users can now import just (myapp) to get the public API.
Circular Dependencies
Sigil does not support circular imports. If module A imports module B, then B cannot import A.
Solutions:
- Extract shared code: Move common definitions to a third module
- Dependency injection: Pass procedures as parameters
- Restructure: Rethink module boundaries
Best Practices
1. Single Responsibility
Each module should have one clear purpose:
;; Good: focused modules
(myapp config) ; Configuration handling
(myapp logging) ; Logging utilities
(myapp http) ; HTTP client
;; Avoid: kitchen-sink modules
(myapp utils) ; Contains everything2. Minimal Exports
Export only what users need:
;; Good: clean interface
(export
connect
disconnect
send-message)
;; Avoid: exposing internals
(export
connect disconnect send-message
internal-buffer retry-count socket-handle)3. Clear Naming
Use descriptive names that indicate the module's purpose:
(myapp user-authentication) ; Clear
(myapp ua) ; Unclear4. Documentation
Document public APIs:
(define-library (myapp http)
(export
;; Connect to a URL, returns a connection or #f on failure
http-connect
;; Send a GET request, returns response body as string
http-get
;; Close a connection
http-close)
...)5. Test Modules Separately
Create corresponding test modules:
myapp/
├── http.sgl
└── test/
└── test-http.sglCompilation
When you use sigil build, modules are automatically compiled to bytecode (.sgb files) which load faster than source.
For standalone applications created with sigil bundle, all modules are bundled into the executable.