#lang scribble/doc @(require "mz.ss" (for-label racket/package)) @(define pack-eval (make-base-eval)) @interaction-eval[#:eval pack-eval (require racket/package)] @title[#:tag "package"]{Limiting Scope: @racket[define-package], @racket[open-package], ...} @note-lib-only[racket/package] @deftogether[( @defform[(define-package package-id exports form ...)] @defform/subs[(open-package package-id) ([exports (id ...) (code:line #:only (id ...)) #:all-defined (code:line #:all-defined-except (id ...))])] )]{ @margin-note{The @racket[define-package] form is based on the @racketidfont{module} form of Chez Scheme @cite["Waddell99"].} The @racket[define-package] form is similar to @racket[module], except that it can appear in any definition context. The @racket[form]s within a @racket[define-package] form can be definitions or expressions; definitions are not visible outside the @racket[define-package] form, but @racket[exports] determines a subset of the bindings that can be made visible outside the package using the definition form @racket[(open-package package-id)]. The @racket[(id ...)] and @racket[#:only (id ...)] @racket[exports] forms are equivalent: exactly the listed @racket[id]s are exported. The @racket[#:all-defined] form exports all definitions from the package body, and @racket[#:all-defined-except (id ...)] exports all definitions except the listed @racket[id]s. All of the usual definition forms work within a @racket[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, @racket[define-package] handles @racket[define*], @racket[define*-syntax], @racket[define*-values], @racket[define*-syntaxes], and @racket[open*-package] specially: the bindings introduced by those forms within a @racket[define-package] body are visible only to @racket[form]s that appear later in the body, and they can shadow any binding from preceding @racket[form]s (even if the preceding binding did not use one of the special @racketidfont{*} definition forms). If an exported identifier is defined multiple times, the last definition is the exported one. @examples[ #:eval pack-eval (define-package presents (doll) (define doll "Molly Coddle") (define robot "Destructo")) doll robot (open-package presents) doll 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 ]} @defform[(package-begin form ...)]{ Similar to @racket[define-package], but it only limits the visible of definitions without binding a package name. If the last @racket[form] is an expression, then the expression is in @tech{tail position} for the @racket[package-begin] form, so that its result is the @racket[package-begin] result. A @racket[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 @racket[package-begin]). @examples[ #:eval pack-eval (package-begin (define secret "mimi") (list secret)) secret ]} @deftogether[( @defidform[define*] @defidform[define*-values] @defidform[define*-syntax] @defidform[define*-syntaxes] @defidform[open*-package] )]{ Equivalent to @racket[define], @racket[define-values], @racket[define-syntax], @racket[define-syntaxes], and @racket[open-package], except within a @racket[define-package] or @racket[package-begin] form, where they create bindings that are visible only to later body forms. @examples[ #:eval pack-eval (define-package mail (cookies) (define* cookies (list 'sugar)) (define* cookies (cons 'chocolate-chip cookies))) (open-package mail) cookies (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)]} @deftogether[( @defproc[(package? [v any/c]) boolean?] @defproc[(package-exported-identifiers [id identifier?]) (listof identifier?)] @defproc[(package-original-identifiers [id identifier?]) (listof identifier?)] )]{ The @racket[package?], @racket[package-exported-identifiers], and @racket[package-original-identifiers] functions are exported @racket[for-syntax] by @racketmodname[racket/package]. The @racket[package?] predicate returns @racket[#t] if @racket[v] is a package value as obtained by @racket[syntax-local-value] on an identifier that is bound to a package. Given such an identifier, the @racket[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 @racket[package-original-identifiers] function returns a parallel list of identifiers for existing bindings of package's exports.} @; ---------------------------------------------------------------------- @close-eval[pack-eval]