Modules
In order to support a growing codebase, Steel has module support for projects spanning multiple files. Steel files can provide
values (with contracts attached) and require
modules from other files:
;; main.scm
(require "provide.scm")
(even->odd 10)
;; provide.scm
(provide
(contract/out even->odd (->/c even? odd?))
no-contract
flat-value)
(define (even->odd x)
(+ x 1))
(define (accept-number x) (+ x 10))
(define (no-contract) "cool cool cool")
(define flat-value 15)
(displayln "Calling even->odd with some bad inputs but its okay")
(displayln (even->odd 1))
Here we can see if we were to run main
that it would include the contents of provide
, and only provided values would be accessible from main
. The contract is attached at the contract boundary, so inside the provide
module, you can violate the contract, but outside the module the contract will be applied.
A few notes on modules:
- Cyclical dependencies are not allowed
- Modules will be only compiled once and used across multiple files. If
A
requiresB
andC
, andB
requiresC
,C
will be compiled once and shared betweenA
andB
. - Modules will be recompiled when changed, and any dependent files will also be recompiled as necessary
Modifiers for requiring
(require (prefix-in export. ;; prefix-in will prefix all of the bound identifiers with the given prefix
(only-in "export.scm" ;; only-in will only introduce the identifiers listed.
thing-should-not-escape
Applesauce
bananas
new-identifier
my-fun-contracted-function
contract-out-test)))
If no modifiers are given, require
-ing a module will introduce all of the provided values into the top level scope.
Providing and requiring macros;
Macros defined using define-syntax
can be handled just like normal values:
;; main.scm
(require "provide.scm")
(foo-bar x) ;; Will expand into (displayln "Hello world")
;; provide.scm
(provide foo-bar)
(define-syntax foo-bar
(syntax-rules ()
[(foo-bar x) (displayln "Hello world!")]))
The module system will take care to keep the namespaces separate - any macros that expand into macros that exist in the originating module will be expanded, but those will not be available to the requiring module. In addition, macros can expand into private values (those that are not provided), and the will still be inaccessible from the requiring module.