The package
form provides fine-grained control over binding
visiblilty. 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 identifer 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 identifers 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 name
s 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:p
is 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-syntax
package2 (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-syntax
open2 (syntax-rules () [(_ name) (open name)])) (let () (package p (x) (define x 1)) (open2 p) x) ; =>1
(define-syntax
package3 (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 (dot
p x)) ; =>3
(
SYNTAX
define-dot
variable name ···1
)
Defineds 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
veriable 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 ···1variable
. formals
)
(
SYNTAX
define*-syntax
variable expr
)
(
SYNTAX
define*-syntax
)(
expr ···1variable
. formals
)
(
SYNTAX
define*-values
)(
exprvariable
···)
(
SYNTAX
define*-syntaxes
)(
exprvariable
···)
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.