Bindings can be defined in one module and shared with another. The defining module is exporting bindings; the other module is importing them. In practice, an importing or exporting module is usually a self-contained source file. But everything here applies equally to submodules, which can share bindings the same way.
It’s conventional to think about importing & exporting in terms of bindings rather than variables. Why? Because a variable = an identifier + a binding. While it’s often true that a binding travels with its original identifier, it’s not mandatory—as we will see below, the identifier can be altered along the way (though the binding will not be).
By default, all bindings defined in a module are private to that module. To make a binding available to other modules, use provide:
Though provide can be used anywhere within a module, Racketeers often consolidate them at the top, to summarize the public interface of the module:
To export every binding newly defined within a module, use the shorthand all-defined-out:
1 2 3 4 5 6 | #lang br (provide (all-defined-out)) ;; same as `(provide my-var another-var third-var)` (define my-var 42) (define another-var 96) (define third-var 256) |
Any bindings available in the module can be exported, not just those that are defined there. For instance, bindings that are already available through the current #lang can also be exported:
These bindings, however, are not included in all-defined-out. To export bindings that have been imported from a certain module, list them individually, or use all-from-out to export all of them:
1 2 | #lang br (provide (all-from-out br)) |
To make the external name of a binding different from its internal name, use provide with rename-out:
A practical use of rename-out is to chain together #%module-begin macros in a language. In this example from bf, the identifier #%module-begin is used twice: within the module it refers to the #%module-begin macro from br/quicklang; outside the module, it will refer to bf-module-begin:
1 2 3 4 5 6 | #lang br/quicklang (define-macro (bf-module-begin PARSE-TREE) #'(#%module-begin ; from `br/quicklang` PARSE-TREE)) (provide (rename-out [bf-module-begin #%module-begin])) |
Every module gets its initial set of bindings from its expander. In a module expression, the expander is designated explicitly. In a source file, the #lang line specifies a reader, which converts the source file into a module expression with an expander designation (see the #lang line for more about this conversion):
1 2 3 4 5 6 | #lang br ;; all bindings exported by the `br` expander are available here (module sub pollen ;; all bindings exported by `pollen` are available here ) |
Beyond that, bindings can be imported from other modules with require:
1 2 | #lang br (token 'FOO "bar") ; no binding for `token` yet |
1 | token: unbound identifier in module in: token |
1 | (token-struct 'FOO "bar" #f #f #f #f #f) |
Bindings can be imported from submodules by using submod, which uses a path-like specification:
The evaluation of a module occurs in a series of separate phases. Consequently, each phase gets its own separate round of importing & exporting. Bindings that are imported during a certain phase are not automatically visible in other phases.
Though the behavior is sensible, it can lead to seemingly mysterious errors—especially when writing macros, which naturally straddle phase 1 (where the macro is compiled) and phase 0 (where the macro is run).
For instance, this macro returns code that relies on nand, a function imported from racket/bool:
1 2 3 4 5 | #lang br (require racket/bool) (define-macro (nander) #'(println (and (nand #f #t) 'phase-0))) (nander) ; 'phase-0 |
This works because an ordinary require, as seen here, imports bindings at phase 0. The macro refers to nand within the syntax object it returns. Though the macro is compiled during phase 1, its syntax object isn’t evaluated until phase 0. So this reference to nand works.
This macro, however, fails with a nand: undefined error:
This time, the macro also tries to use nand outside the syntax object. This reference to nand will be evaluated during phase 1, when the macro is compiled. But racket/bool isn’t available in phase 1—only phase 0. Hence the error.
This problem can be cured with for-syntax, which explicitly imports a module at phase 1, where it can be visible to macros:
1 2 3 4 5 6 7 | #lang br (require racket/bool ; makes `nand` visible at phase 0 (for-syntax racket/bool)) ; makes it visible at phase 1 (define-macro (nander) (println (and (nand #f #t) 'phase-1)) #'(println (and (nand #f #t) 'phase-0))) (nander) |
1 2 | 'phase-1 'phase-0 |
And just to come full circle: if the phase-0 require for racket/bool is removed, the nand inside the macro (at phase 1) will still print, but back in phase 0, an unbound-identifier error will arise:
1 2 3 4 5 6 | #lang br (require (for-syntax racket/bool)) ; only visible at phase 1 (define-macro (nander) (println (and (nand #f #t) 'phase-1)) #'(println (and (nand #f #t) 'phase-0))) (nander) |
1 2 | 'phase-1 nand: unbound identifier in module in: nand |
Imports in the Racket Guide
Exports in the Racket Guide
Importing and Exporting in the Racket Reference