The package form provides fine-grained control over binding
visibility. A package is an expansion-time entity only; it has no
run-time identity.The package and open constructs
correspond to module and import in Chez Scheme. The
package* and open* constructs correspond to structures
in Standard ML (without types).
( SYNTAX
package name )(export ···) body-expr-or-defn ···1
( SYNTAX
package name )all-defined body-expr-or-defn ···1
Defines name (in any definition context) to a compile-time
package description, much in the way that ( binds define-syntax a
(syntax-rules ...))a to a syntax expander, or
(define-struct a ()) binds a to a compile-time
structure type description.
Each export must be an identifier that is defined within the
package body. The all-defined variant is shorthand for listing
all identifiers that are defined in the package body.
Although package does not introduce a new binding scope, it
hides all of the definitions in its body from definitions and
expressions that are outside the package. The exported definitions
become visible only when the package is opened with forms such as
open.
Each body-expr-or-defn can be a definition or expression. Each
defined identifier is visible in the entire package body, except
definitions introduced by define*, define*-syntax,
define*-values, define*-syntaxes, open*,
package*, or define*-dot. The * forms expose
identifiers to expressions and definitions that appear later in the
package body, only, much like the sequential binding of
let*. As with let*, an identifier can be defined
multiple times within the package using * forms; if such an
identifier is exported, the export corresponds to the last
definition. For any other form of definition, the identifiers that it
defines must be defined only once within the package.
When used in an internal-definition context (see
section 2.8.5 in PLT MzScheme: Language Manual), name is immediately available for use
with other forms, such as open, in the same
internal-definition sequence.
For example, see open, below.
( SYNTAX
package* name )(export ···) body-expr-or-defn ···1
( SYNTAX
package* name )all-defined body-expr-or-defn ···1
Like package, but within a package body, the package name is
visible only to later definitions and expressions.
( SYNTAX
open name ···1)
If a single name is provided, it must be defined as a package,
and the package's exports are exposed in the definition context of
the open declaration.
The open form acts like a definition form, in that it
introduces bindings in a definition context, and such bindings can be
exported from a package (even using all-defined). More
precisely, however, open exposes bindings hidden by a package,
rather than introducing identifiers. This exposure overrides any
identifier that would shadow the binding (were it not hidden by the
package in the first place).
If multiple names are provided, the first name must correspond
to a defined package, the second must correspond to a package
exported from the first, and so on. Only the package corresponding to
the last name is opened into the open's definition context.
Examples:
(package p (f) (define (f a) (+ a x)) (define x 1)) (f 0) ; => error: reference to undefined identifierf(let ([p 5]) (open p) ...) ; => error:pis not a package name (open p) (f 0) ; =>1(let ([f (lambda (x) x)]) (open p) (f 0)) ; =>1(let ([x 2]) (open p) (f 0)) ; =>1(package p (p2) (package p2 (f) (define (f a) (- a x))) (define x 2)) (open p p2) (f 3) ; =>1(package p (p2) (package p2 (f) (define (f a) (- a x))) (define x 2)) (open p p2) (f 3) ; =>1(package p1 (x f1 p2 p3) (define x 1) (define (f1) x) (package p2 (x f2) (define x 2) (define (f2) x)) (package p3 (f3) (open p2) (define (f3) x))) (open p1) x ; =>1(f1) ; =>1(open p2) x ; =>2(f2) ; =>2(open p3) (f3) ; =>2(open p1) x ; =>1(define-syntaxpackage2 (syntax-rules () [(_ name id def) (package name (id foo) def (define foo 3))])) (let () (package2 p foo (define foo 1)) (open p) foo) ; =>1(let () (package2 p bar (define bar 1)) (open p) foo) ; => error: reference to undefined identifierfoo(define-syntaxopen2 (syntax-rules () [(_ name) (open name)])) (let () (package p (x) (define x 1)) (open2 p) x) ; =>1(define-syntaxpackage3 (syntax-rules () [(_ name id) (package name (id foo) (define (id) foo) (define foo 3))])) (let ([foo 17]) (package3 p f) (open p) (+ foo (f))) ; =>20
( SYNTAX
open* name ···1)
Like open, but within a package, the opened package's exports
are exposed only to later definitions and expressions.
( SYNTAX
dot name ···1export)
Equivalent to ( when let () (open name ···1)
export)export is exported from the package
selected by .name ···1
Example:
(package p (x) (define x 1)) (+ 2 (dotp x)) ; =>3
( SYNTAX
define-dot variable name ···1)
Defines variable as an alias for the package export selected by
. The export can correspond to a nested
package, in which case the alias is available for immediate use in
forms like name ···1open or define-dot.
( SYNTAX
define*-dot variable name ···1)
Like define-dot, but within a package, the alias applies only
to later definitions and expressions.
( SYNTAX
rename-potential-package old-name new-name)
Introduces old-name as an alias for new-name.
Although make-rename-transformer (see section 12.6 in PLT MzScheme: Language Manual)
can be used to create an alias for a package name, only an alias
created by rename-potential-package, define-dot, or
define*-dot is available for immediate use by forms such as
open.
( SYNTAX
define* variable expr)
( SYNTAX
define* )( expr ···1header . formals)
( SYNTAX
define*-syntax variable expr)
( SYNTAX
define*-syntax )( expr ···1header . formals)
( SYNTAX
define*-values )( exprvariable ···)
( SYNTAX
define*-syntaxes )( exprvariable ···)
( SYNTAX
rename*-potential-package old-name new-name)
Like define, etc., but when used in a package, they define
identifiers that are visible only to later definitions and
expressions.
( SYNTAX
package/derived expr name )(export ···) body-expr-or-defn ···1
( SYNTAX
package/derived expr name )all-defined body-expr-or-defn ···1
Like package, but syntax errors (such as duplicate definitions)
are reported as originating from expr.
This form is useful for writing macros that expand to package
and rely on the syntax checks of the package transformer, but
where syntax errors should be reported in terms of the source
expression or declaration.
( SYNTAX
open/derived expr orig-name name ···1)
( SYNTAX
open*/derived expr orig-name name ···1)
Like open and open*, but syntax errors (such as
duplicate definitions) are reported as originating from expr.
Furthermore, if name is not a package name, the error message
reports that orig-name is not defined as a package.