On this page:
define-package
open-package
package-begin
define*
define*-values
define*-syntax
define*-syntaxes
open*-package
package?
package-exported-identifiers
package-original-identifiers

2.23 Limiting Scope: define-package, open-package, ...

The bindings documented in this section are provided by the racket/package library, not racket/base or racket.

(define-package package-id exports form ...)
(open-package package-id)
 
exports = (id ...)
  | #:only (id ...)
  | #:all-defined
  | #:all-defined-except (id ...)

The define-package form is based on the module form of Chez Scheme [Waddell99].

The define-package form is similar to module, except that it can appear in any definition context. The forms within a define-package form can be definitions or expressions; definitions are not visible outside the define-package form, but exports determines a subset of the bindings that can be made visible outside the package using the definition form (open-package package-id).

The (id ...) and #:only (id ...) exports forms are equivalent: exactly the listed ids are exported. The #:all-defined form exports all definitions from the package body, and #:all-defined-except (id ...) exports all definitions except the listed ids.

All of the usual definition forms work within a define-package body, and such definitions are visible to all expressions within the body (and, in particular, the definitions can refer to each other). However, define-package handles define*, define*-syntax, define*-values, define*-syntaxes, and open*-package specially: the bindings introduced by those forms within a define-package body are visible only to forms that appear later in the body, and they can shadow any binding from preceding forms (even if the preceding binding did not use one of the special * definition forms). If an exported identifier is defined multiple times, the last definition is the exported one.

Examples:

> (define-package presents (doll)
    (define doll "Molly Coddle")
    (define robot "Destructo"))
> doll

reference to undefined identifier: doll

> robot

reference to undefined identifier: robot

> (open-package presents)
> doll

"Molly Coddle"

> robot

reference to undefined identifier: robot

> (define-package big-russian-doll (middle-russian-doll)
    (define-package middle-russian-doll (little-russian-doll)
      (define little-russian-doll "Anastasia")))
> (open-package big-russian-doll)
> (open-package middle-russian-doll)
> little-russian-doll

"Anastasia"

(package-begin form ...)
Similar to define-package, but it only limits the visible of definitions without binding a package name. If the last form is an expression, then the expression is in tail position for the package-begin form, so that its result is the package-begin result.

A package-begin form can be used as an expression, but if it is used in a context where definitions are allowed, then the definitions are essentially spliced into the enclosing context (though the defined bindings remain hidden outside the package-begin).

Examples:

> (package-begin
    (define secret "mimi")
    (list secret))

'("mimi")

> secret

reference to undefined identifier: secret

Equivalent to define, define-values, define-syntax, define-syntaxes, and open-package, except within a define-package or package-begin form, where they create bindings that are visible only to later body forms.

Examples:

> (define-package mail (cookies)
    (define* cookies (list 'sugar))
    (define* cookies (cons 'chocolate-chip cookies)))
> (open-package mail)
> cookies

'(chocolate-chip sugar)

> (define-syntax-rule (define-seven id) (define id 7))
> (define-syntax-rule (define*-seven id)
    (begin
      (define-package p (id) (define-seven id))
      (open*-package p)))
> (package-begin
    (define vii 8)
    (define*-seven vii)
    vii)

compile: cannot use identifier tainted by macro

transformation in: lambda

The package? predicate returns #t if v is a package value as obtained by syntax-local-value on an identifier that is bound to a package.

Given such an identifier, the package-exported-identifiers function returns a list of identifiers that correspond to the bindings that would be introduced by opening the package in the lexical context being expanded. The package-original-identifiers function returns a parallel list of identifiers for existing bindings of package’s exports.