280 lines
9.0 KiB
Racket
280 lines
9.0 KiB
Racket
#lang scribble/doc
|
|
@(require "common.ss"
|
|
scribble/eval
|
|
(for-label mzlib/etc
|
|
scheme/bool
|
|
scheme/local
|
|
setup/dirs
|
|
(only-in scheme build-list build-string build-vector
|
|
symbol=?)))
|
|
|
|
@(define etc-eval (make-base-eval))
|
|
@interaction-eval[#:eval etc-eval (require mzlib/etc)]
|
|
|
|
@(begin
|
|
(define-syntax-rule (bind id else-id)
|
|
(begin
|
|
(require (for-label scheme/base))
|
|
(define id (scheme lambda))
|
|
(define else-id (scheme else))))
|
|
(bind base-lambda base-else))
|
|
|
|
@mzlib[#:mode title etc]
|
|
|
|
The @schememodname[mzlib/etc] library re-exports the following
|
|
@schememodname[scheme/base] and other libraries:
|
|
|
|
@schemeblock[
|
|
boolean=?
|
|
true
|
|
false
|
|
build-list
|
|
build-string
|
|
build-vector
|
|
compose
|
|
local
|
|
symbol=?
|
|
]
|
|
|
|
@defform[(begin-lifted expr ...+)]
|
|
|
|
Lifts the @scheme[expr]s so that they are evaluated once at the ``top
|
|
level'' of the current context, and the result of the last
|
|
@scheme[expr] is used for every evaluation of the
|
|
@scheme[begin-lifted] form.
|
|
|
|
When this form is used as a run-time expression within a module, the
|
|
``top level'' corresponds to the module's top level, so that each
|
|
@scheme[expr] is evaluated once for each invocation of the
|
|
module. When it is used as a run-time expression outside of a module,
|
|
the ``top level'' corresponds to the true top level. When this form is
|
|
used in a @scheme[define-syntax], @scheme[letrec-syntax],
|
|
etc. binding, the ``top level'' corresponds to the beginning of the
|
|
binding's right-hand side. Other forms may redefine ``top level''
|
|
(using @scheme[local-expand/capture-lifts]) for the expressions that
|
|
they enclose.
|
|
|
|
|
|
@defform[(begin-with-definitions defn-or-expr ...)]{
|
|
|
|
Supports a mixture of expressions and mutually recursive definitions,
|
|
much like a @scheme[module] body. Unlike in a @scheme[module],
|
|
however, syntax definitions cannot be used to generate other immediate
|
|
definitions (though they can be used for expressions).
|
|
|
|
The result of the @scheme[begin-with-definitions] form is the result
|
|
of the last @scheme[defn-or-expr] if it is an expression,
|
|
@|void-const| otherwise. If no @scheme[defn-or-expr] is provided
|
|
(after flattening @scheme[begin] forms), the result is @|void-const|.}
|
|
|
|
|
|
|
|
@defform[(define-syntax-set (id ...) defn ...)]{
|
|
|
|
Similar to @scheme[define-syntaxes], but instead of a single body
|
|
expression, a sequence of definitions follows the sequence of defined
|
|
identifiers. For each @scheme[identifier], the @scheme[defn]s should
|
|
include a definition for @scheme[id]@schemeidfont{/proc}. The value
|
|
for @scheme[id]@schemeidfont{/proc} is used as the (expansion-time)
|
|
value for @scheme[id].
|
|
|
|
The @scheme[define-syntax-set] form is useful for defining a set of
|
|
syntax transformers that share helper functions, though
|
|
@scheme[begin-for-syntax] now serves essentially the same purposes.
|
|
|
|
@as-examples[
|
|
@schemeblock[
|
|
(define-syntax-set (let-current-continuation
|
|
let-current-escape-continuation)
|
|
(define (mk call-id)
|
|
(lambda (stx)
|
|
(syntax-case stx ()
|
|
[(_ id body1 body ...)
|
|
(with-syntax ([call call-id])
|
|
(syntax (call (lambda (id) body1 body ...))))])))
|
|
(define let-current-continuation/proc
|
|
(mk (quote-syntax call/cc)))
|
|
(define let-current-escape-continuation/proc
|
|
(mk (quote-syntax call/ec))))
|
|
]]}
|
|
|
|
|
|
@defform*[#:literals (else)
|
|
[(evcase key-expr (value-expr body-expr ...) ...+)
|
|
(evcase key-expr (value-expr body-expr ...) ... [else body-expr ...])]]{
|
|
|
|
The @scheme[evcase] form is similar to @scheme[case], except that
|
|
expressions are provided in each clause instead of a sequence of
|
|
data. After @scheme[key-expr] is evaluated, each @scheme[value-expr]
|
|
is evaluated until a value is found that is @scheme[eqv?] to the key
|
|
value; when a matching value is found, the corresponding
|
|
@scheme[body-expr]s are evaluated and the value(s) for the last is the
|
|
result of the entire @scheme[evcase] expression.
|
|
|
|
The @scheme[else] literal is recognized either as unbound (like in the
|
|
@schememodname[mzscheme] language) or bound as @|base-else| from
|
|
@schememodname[scheme/base].}
|
|
|
|
|
|
@defproc[(identity [v any/c]) any/c]{
|
|
|
|
Returns @scheme[v].}
|
|
|
|
|
|
@defform/subs[#:literals (val rec vals recs _ values)
|
|
(let+ clause body-expr ...+)
|
|
([clause (val target expr)
|
|
(rec target expr)
|
|
(vals (target ...) expr)
|
|
(recs (target expr) ...)
|
|
(_ expr ...)]
|
|
[target id
|
|
(values id ...)])]{
|
|
|
|
A binding construct that specifies scoping on a per-binding basis
|
|
instead of a per-expression basis. It helps eliminate rightward-drift
|
|
in programs. It looks similar to @scheme[let], except each clause has
|
|
an additional keyword tag before the binding variables.
|
|
|
|
Each @scheme[clause] has one of the following forms:
|
|
|
|
@itemize{
|
|
|
|
@item{@scheme[(val target expr)] : Binds @scheme[target]
|
|
non-recursively to @scheme[expr].}
|
|
|
|
@item{@scheme[(rec target expr)] : Binds @scheme[target] recursively to
|
|
@scheme[expr].}
|
|
|
|
@item{@scheme[(vals (target expr) ...)] : The @scheme[target]s are
|
|
bound to the @scheme[expr]s. The environment of the @scheme[expr]s is
|
|
the environment active before this clause.}
|
|
|
|
@item{@scheme[(recs (target expr) ...)] : The @scheme[targets]s are
|
|
bound to the @scheme[expr]s. The environment of the @scheme[expr]s
|
|
includes all of the @scheme[targets]s.}
|
|
|
|
@item{@scheme[(_ expr ...)] : Evaluates the @scheme[expr]s without
|
|
binding any variables.}
|
|
|
|
}
|
|
|
|
The clauses bind left-to-right. When a @scheme[target] is
|
|
@scheme[(values id ...)], multiple values returned by the
|
|
corresponding expression are bound to the multiple variables.
|
|
|
|
@examples[
|
|
#:eval etc-eval
|
|
(let+ ([val (values x y) (values 1 2)])
|
|
(list x y))
|
|
|
|
(let ([x 1])
|
|
(let+ ([val x 3]
|
|
[val y x])
|
|
y))
|
|
]}
|
|
|
|
|
|
@defproc[(loop-until [start any/c] [done? (any/c . -> . any)]
|
|
[next (any/c . -> . any/c)]
|
|
[f (any/c . -> . any)])
|
|
void?]{
|
|
|
|
Repeatedly invokes the @scheme[f] procedure until the @scheme[done?]
|
|
procedure returns @scheme[#t]:
|
|
|
|
@schemeblock[
|
|
(define (loop-until start done? next f)
|
|
(let loop ([i start])
|
|
(unless (done? i)
|
|
(f i)
|
|
(loop (next i)))))
|
|
]}
|
|
|
|
|
|
@defproc[(namespace-defined? [sym symbol?]) boolean?]{
|
|
|
|
Returns @scheme[#t] if @scheme[namespace-variable-value] would return
|
|
a value for @scheme[sym], @scheme[#f] otherwise.}
|
|
|
|
|
|
@defform[(nand expr ...)]{
|
|
|
|
Same as @scheme[(not (and expr ...))].}
|
|
|
|
|
|
@defform[(nor expr ...)]{
|
|
|
|
Same as @scheme[(not (or expr ...))].}
|
|
|
|
|
|
@defform[(opt-lambda formals body ...+)]{
|
|
|
|
Supports optional (but not keyword) arguments like @base-lambda from
|
|
@scheme[scheme/base].}
|
|
|
|
|
|
@defform[(recur id bindings body ...+)]{
|
|
|
|
Equivalent to @scheme[(let id bindings body ...+)].}
|
|
|
|
|
|
@defform*[[(rec id value-expr)
|
|
(rec (id arg-id ...) expr)
|
|
(rec (id arg-id ... . rest-id) expr)]]{
|
|
|
|
Equivalent, respectively, to
|
|
|
|
@schemeblock[
|
|
(letrec ([id value-expr]) id)
|
|
(letrec ([id (lambda (arg-id ...) value-expr)]) id)
|
|
(letrec ([id (lambda (arg-id ... . rest-id) value-expr)]) id)
|
|
]}
|
|
|
|
|
|
@defform*[[(this-expression-source-directory)
|
|
(this-expression-source-directory datum)]]{
|
|
|
|
@margin-note{See @schememodname[scheme/runtime-path] for a definition form
|
|
that works better when creating executables.}
|
|
|
|
Expands to an expression that evaluates to the directory of the file
|
|
containing the source @scheme[datum]. If @scheme[datum] is not
|
|
supplied, then the entire @scheme[(this-expression-source-directory)]
|
|
expression is used as @scheme[datum].
|
|
|
|
If @scheme[datum] has a source module, then the expansion attempts to
|
|
determine the module's run-time location. This location is determined
|
|
by preserving the lexical context of @scheme[datum] in a syntax
|
|
object, extracting its source module path at run time, and then
|
|
resolving the module path.
|
|
|
|
Otherwise, @scheme[datum]'s source file is determined through source
|
|
location information associated with @scheme[datum], if it is
|
|
present. As a last resort, @scheme[current-load-relative-directory] is
|
|
used if it is not @scheme[#f], and @scheme[current-directory] is used
|
|
if all else fails.
|
|
|
|
A directory path derived from source location is always stored in
|
|
bytes in the expanded code, unless the file is within the result of
|
|
@scheme[find-collects-dir], in which case the expansion records the
|
|
path relative to @scheme[(find-collects-dir)] and then reconstructs it
|
|
using @scheme[(find-collects-dir)] at run time.}
|
|
|
|
|
|
@defform*[[(this-expression-file-name)
|
|
(this-expression-file-name datum)]]{
|
|
|
|
Similar to @scheme[this-expression-source-directory], except that only
|
|
source information associated with @scheme[datum] or
|
|
@scheme[(this-expression-file-name)] is used to extract a filename. If
|
|
no filename is available, the result is @scheme[#f].}
|
|
|
|
|
|
@defform[#:literals (quote unsyntax scheme)
|
|
(hash-table (#,(scheme quote) flag) ... (key-expr val-expr) ...)]{
|
|
|
|
Creates a new hash-table providing the quoted flags (if any) to
|
|
@scheme[make-hash-table], and then mapping each key to the
|
|
corresponding values.}
|