work on guide, and fix problems with scribble/eval
svn: r8250
This commit is contained in:
parent
8f0f4fcdf9
commit
343308481a
|
@ -193,7 +193,7 @@
|
|||
[comment? (lambda (a)
|
||||
(and (pair? a)
|
||||
(or (eq? (car a) 'code:comment)
|
||||
(and (identifier? a)
|
||||
(and (identifier? (car a))
|
||||
(eq? (syntax-e (car a)) 'code:comment)))))])
|
||||
(if (or (comment? a)
|
||||
(and (syntax? a) (comment? (syntax-e a))))
|
||||
|
@ -217,12 +217,15 @@
|
|||
ev
|
||||
catching-exns?
|
||||
(let ([s (strip-comments s)])
|
||||
(if (syntax? s)
|
||||
(syntax-case s (module)
|
||||
[(module . _rest)
|
||||
(syntax->datum s)]
|
||||
[_else s])
|
||||
s))))
|
||||
(cond
|
||||
[(syntax? s)
|
||||
(syntax-case s (module)
|
||||
[(module . _rest)
|
||||
(syntax->datum s)]
|
||||
[_else s])]
|
||||
[(string? s)
|
||||
`(begin ,s)]
|
||||
[else s]))))
|
||||
list))
|
||||
|
||||
(define-syntax-rule (quote-expr e) 'e)
|
||||
|
@ -262,9 +265,7 @@
|
|||
(list " ")))
|
||||
|
||||
(define-syntax (schemedefinput* stx)
|
||||
(syntax-case stx (eval-example-string define define-values define-struct)
|
||||
[(_ (eval-example-string s))
|
||||
#'(schemeinput* (eval-example-string s))]
|
||||
(syntax-case stx (define define-values define-struct)
|
||||
[(_ (define . rest))
|
||||
(syntax-case stx ()
|
||||
[(_ e) #'(schemeblock+line e)])]
|
||||
|
|
|
@ -1861,26 +1861,28 @@
|
|||
#f
|
||||
(append
|
||||
(if author
|
||||
(list author
|
||||
", ")
|
||||
(append (decode-content (list author))
|
||||
(list ", "))
|
||||
null)
|
||||
(list 'ldquo
|
||||
title
|
||||
(if location
|
||||
(list 'ldquo)
|
||||
(decode-content (list title))
|
||||
(list (if location
|
||||
","
|
||||
".")
|
||||
'rdquo)
|
||||
(if location
|
||||
(list " "
|
||||
location
|
||||
(if date
|
||||
","
|
||||
"."))
|
||||
(cons " "
|
||||
(append
|
||||
(decode-content (list location))
|
||||
(list
|
||||
(if date
|
||||
","
|
||||
"."))))
|
||||
null)
|
||||
(if date
|
||||
(list " "
|
||||
date
|
||||
".")
|
||||
(cons " "
|
||||
(append (decode-content (list date))
|
||||
(list ".")))
|
||||
null)
|
||||
(if url
|
||||
(list " "
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
@title[#:tag "drawing-overview"]{Drawing}
|
||||
|
||||
Drawing in MrEd requires a @deftech{device context} (@deftech{DC}),
|
||||
which is an instance of the @scheme[dc<%>] interface. For example,
|
||||
the @method[canvas<%> get-dc] method of a canvas returns a
|
||||
@scheme[dc<%>] instance for drawing into the canvas window. Other
|
||||
kinds of DCs draw to different kinds of devices:
|
||||
Drawing in PLT Scheme requires a @deftech{device context}
|
||||
(@deftech{DC}), which is an instance of the @scheme[dc<%>]
|
||||
interface. For example, the @method[canvas<%> get-dc] method of a
|
||||
canvas returns a @scheme[dc<%>] instance for drawing into the canvas
|
||||
window. Other kinds of DCs draw to different kinds of devices:
|
||||
|
||||
@itemize{
|
||||
|
||||
|
|
|
@ -313,7 +313,7 @@ can be read using these methods or written using
|
|||
@scheme[write-editor-global-header] and
|
||||
@scheme[write-editor-global-footer].
|
||||
|
||||
When reading from streams that span MrEd versions, use
|
||||
When reading from streams that span PLT Scheme versions, use
|
||||
@scheme[read-editor-version] before this procedure.
|
||||
|
||||
|
||||
|
@ -349,10 +349,10 @@ If @scheme[raise-errors?] is true, then an error in reading triggers an
|
|||
|
||||
This procedure is a load handler for use with @scheme[current-load].
|
||||
|
||||
The handler recognizes MrEd editor-format files (see
|
||||
The handler recognizes PLT Scheme editor-format files (see
|
||||
@secref["editorfileformat"]) and decodes them for loading. It is
|
||||
normally installed as MrEd starts (see
|
||||
@secref[#:doc reference-doc "running-sa"]).
|
||||
normally installed as MrEd starts (see @secref[#:doc reference-doc
|
||||
"running-sa"]).
|
||||
|
||||
The handler recognizes editor files by the first twelve characters of
|
||||
the file: @litchar{WXME01}@nonterm{digit}@nonterm{digit}@litchar{ ## }.
|
||||
|
@ -409,7 +409,7 @@ One or more editors can be written to the stream by calling the
|
|||
@scheme[read-editor-global-header] and
|
||||
@scheme[read-editor-global-footer].
|
||||
|
||||
To support streams that span MrEd versions, use
|
||||
To support streams that span PLT Scheme versions, use
|
||||
@scheme[write-editor-version] before this procedure.
|
||||
|
||||
See also @secref["editorfileformat"].
|
||||
|
|
|
@ -1696,11 +1696,11 @@ If @scheme[fit-on-page?] is a true value, then during printing for a
|
|||
@scheme[text%] editor, the editor's maximum width is set to the width
|
||||
of the page (less margins) and the autowrapping bitmap is removed.
|
||||
|
||||
The @scheme[output-mode] setting is used for Windows and
|
||||
Mac OS X. It determines whether the output is generated
|
||||
directly as a PostScript file (using MrEd's built-in PostScript
|
||||
system) or generated using the platform-specific standard printing
|
||||
mechanism. The possible values are
|
||||
The @scheme[output-mode] setting is used for Windows and Mac OS X. It
|
||||
determines whether the output is generated directly as a PostScript
|
||||
file (using PLT Scheme's built-in PostScript system) or generated
|
||||
using the platform-specific standard printing mechanism. The possible
|
||||
values are
|
||||
|
||||
@itemize{
|
||||
|
||||
|
|
|
@ -23,8 +23,9 @@ The editor toolbox provides a foundation for two common kinds of
|
|||
|
||||
Both kinds of applications need an extensible editor that can handle
|
||||
text, images, programmer-defined items, and even embedded
|
||||
editors. The difference between them is the layout of items. MrEd
|
||||
therefore provides two kinds of editors via two classes:
|
||||
editors. The difference between them is the layout of items. The
|
||||
editor toolbox therefore provides two kinds of editors via two
|
||||
classes:
|
||||
|
||||
@itemize{
|
||||
|
||||
|
@ -36,7 +37,7 @@ Both kinds of applications need an extensible editor that can handle
|
|||
|
||||
}
|
||||
|
||||
MrEd's editor architecture addresses the full range of real-world
|
||||
This editor architecture addresses the full range of real-world
|
||||
issues for an editor---including cut-and-paste, extensible file
|
||||
formats, and layered text styles---while supporting a high level of
|
||||
extensibility. Unfortunately, the system is fairly complex as a
|
||||
|
@ -46,7 +47,7 @@ MrEd's editor architecture addresses the full range of real-world
|
|||
descriptions above to justify the depth and complexity of the toolbox
|
||||
and the learning investment required to use it.
|
||||
|
||||
A brief example illustrates how MrEd editors work. To start, an editor
|
||||
A brief example illustrates how editors work. To start, an editor
|
||||
needs an @scheme[editor-canvas%] to display its contents. Then, we
|
||||
can create a text editor and install it into the canvas:
|
||||
|
||||
|
@ -156,8 +157,8 @@ Applications that use the editor classes typically derive new versions
|
|||
|
||||
@section[#:tag "tb:miaoverview"]{Editor Structure and Terminology}
|
||||
|
||||
MrEd supports extensible and nestable editors by decomposing an editor
|
||||
assembly into three functional parts:
|
||||
The editor toolbox supports extensible and nestable editors by
|
||||
decomposing an editor assembly into three functional parts:
|
||||
|
||||
@itemize{
|
||||
|
||||
|
@ -359,7 +360,7 @@ Editor data is read and written using @scheme[editor-stream-in%] and
|
|||
@scheme[write-editor-global-footer]. Similarly, reading editors from
|
||||
a stream is initialized with @scheme[read-editor-global-header] and
|
||||
finalized with @scheme[read-editor-global-footer]. Optionally, to
|
||||
support streams that span versions of MrEd, use
|
||||
support streams that span versions of PLT Scheme, use
|
||||
@scheme[write-editor-version] and @scheme[read-editor-version] before
|
||||
the header operations.
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ If @scheme[v] is an event in MzScheme's sense (not to be confused with
|
|||
multiple times (but it will complete a @scheme[sync] on @scheme[v] at
|
||||
most one time). If the current thread is the current eventspace's
|
||||
handler thread, events are dispatched until a @scheme[v] sync
|
||||
succeeds on a MrEd event boundary. For other threads, calling
|
||||
succeeds on an event boundary. For other threads, calling
|
||||
@scheme[yield] with a MzScheme event is equivalent to calling
|
||||
@scheme[sync]. In either case, the result is the same that of
|
||||
@scheme[sync]; however, if a wrapper procedure is associated with
|
||||
|
|
|
@ -17,10 +17,11 @@ Only canvas @scheme[dc<%>] and @scheme[bitmap-dc%] objects support
|
|||
@scheme[gl-context<%>] keeps its identity. Canvas contexts are double
|
||||
buffered, and bitmap contexts are single buffered.
|
||||
|
||||
MrEd provides no OpenGL routines. Instead, they must be obtained from
|
||||
a separate library, such as @scheme[(lib "sgl.ss" "sgl")]. MrEd
|
||||
merely manages the current OpenGL context, connecting it to windows
|
||||
and bitmaps.
|
||||
The @schememodname[scheme/gui/base] library provides no OpenGL
|
||||
routines. Instead, they must be obtained from a separate library,
|
||||
such as @schememodname[sgl]. The facilities in
|
||||
@schememodname[scheme/gui/base] merely manage the current OpenGL
|
||||
context, connecting it to windows and bitmaps.
|
||||
|
||||
Only one OpenGL context can be active at a time across all threads and
|
||||
eventspaces. Except under Mac OS X, OpenGL contexts are not protected
|
||||
|
@ -30,7 +31,7 @@ Only one OpenGL context can be active at a time across all threads and
|
|||
only within a thunk passed to @method[gl-context<%> call-as-current],
|
||||
then drawing from the separate threads will not interfere, because
|
||||
@method[gl-context<%> call-as-current] uses a lock to serialize
|
||||
context selection across all threads in MrEd.
|
||||
context selection across all threads in PLT Scheme.
|
||||
|
||||
|
||||
@defmethod[(call-as-current [thunk (-> any)]
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
|
||||
@declare-exporting[scheme/gui/base scheme/gui]
|
||||
|
||||
This reference manual describes the MrEd GUI toolbox that is part of
|
||||
PLT Scheme. See @secref[#:doc '(lib "scribblings/guide/guide.scrbl")
|
||||
"mred"] in @italic{@link["../guide/index.html"]{A Guide to PLT
|
||||
Scheme}} for an introduction to MrEd.
|
||||
This reference manual describes the GUI toolbox that is part of PLT
|
||||
Scheme and whose core is implemented by the MrEd executable.
|
||||
|
||||
@defmodule*/no-declare[(scheme/gui/base)]{The
|
||||
@schememodname[scheme/gui/base] module provides all of the class,
|
||||
interface, and procedure bindings defined in this manual.}
|
||||
@schememodname[scheme/gui/base] library provides all of the class,
|
||||
interface, and procedure bindings defined in this manual. At run time,
|
||||
this library needs primitive graphics support that the MrEd executable
|
||||
provides; this library cannot run in MzScheme.}
|
||||
|
||||
@defmodulelang*/no-declare[(scheme/gui)]{The
|
||||
@schememodname[scheme/gui] language combines all bindings of the
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
@title[#:style '(toc reveal)]{Overview}
|
||||
|
||||
For documentation purposes, the MrEd toolbox is organized into three
|
||||
parts:
|
||||
For documentation purposes, the graphics toolbox is organized into
|
||||
three parts:
|
||||
|
||||
@itemize{
|
||||
|
||||
|
|
|
@ -118,8 +118,8 @@ Hides the cursor until the user moves the mouse or clicks the mouse
|
|||
this function calls the window's @method[top-level-window<%>
|
||||
on-message] method, providing @scheme[message] as the method's
|
||||
argument; the result of the function call is the result returned by
|
||||
the method. If no MrEd window is at the given coordinates, or if it
|
||||
is covered by a non-MrEd window at (@scheme[x], @scheme[y]),
|
||||
the method. If no Scheme window is at the given coordinates, or if it
|
||||
is covered by a non-Scheme window at (@scheme[x], @scheme[y]),
|
||||
@scheme[#f] is returned.
|
||||
|
||||
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
@title[#:tag "windowing-overview"]{Windowing}
|
||||
|
||||
@section{Basic GUI Building Blocks}
|
||||
|
||||
MrEd's windowing toolbox provides the basic building blocks of GUI
|
||||
The PLT Scheme windowing toolbox provides the basic building blocks of GUI
|
||||
programs, including frames (top-level windows), modal dialogs, menus,
|
||||
buttons, check boxes, text fields, and radio buttons. The toolbox
|
||||
provides these building blocks via built-in classes, such as the
|
||||
|
@ -132,7 +130,7 @@ For more information about window layout and containers, see
|
|||
|
||||
@section{Core Windowing Classes}
|
||||
|
||||
The fundamental graphical element in MrEd's windowing toolbox is an
|
||||
The fundamental graphical element in the windowing toolbox is an
|
||||
@deftech{area}. The following classes implement the different types
|
||||
of areas in the windowing toolbox:
|
||||
|
||||
|
@ -320,7 +318,7 @@ system:
|
|||
|
||||
@section[#:tag "containeroverview"]{Geometry Management}
|
||||
|
||||
MrEd's geometry management makes it easy to design windows that look
|
||||
The windowing toolbox's geometry management makes it easy to design windows that look
|
||||
right on all platforms, despite different graphical representations
|
||||
of GUI elements. Geometry management is based on containers; each
|
||||
container arranges its children based on simple constraints, such as
|
||||
|
@ -742,7 +740,7 @@ Despite the programming convenience provided by a purely sequential
|
|||
|
||||
}
|
||||
|
||||
In MrEd, an @deftech{eventspace} is a context for processing GUI
|
||||
An @deftech{eventspace} is a context for processing GUI
|
||||
events. Each eventspace maintains its own queue of events, and events
|
||||
in a single eventspace are dispatched sequentially by a designated
|
||||
@deftech{handler thread}. An event-handling procedure running in this
|
||||
|
|
47
collects/scribblings/guide/case.scrbl
Normal file
47
collects/scribblings/guide/case.scrbl
Normal file
|
@ -0,0 +1,47 @@
|
|||
#lang scribble/doc
|
||||
@require[scribble/manual]
|
||||
@require[scribble/eval]
|
||||
@require["guide-utils.ss"]
|
||||
@require[(for-label scheme/match)]
|
||||
|
||||
@title{Simple Dispatch: @scheme[case]}
|
||||
|
||||
The @scheme[case] form dispatches to a clause by matching the result
|
||||
of an expression to the values for the clause:
|
||||
|
||||
@specform[(case expr
|
||||
[(datum ...+) expr ...+]
|
||||
...)]
|
||||
|
||||
Each @scheme[_datum] will be compared to the result of the first
|
||||
@scheme[_expr] using @scheme[eqv?]. Since @scheme[eqv?] doesn't work on
|
||||
many kinds of values, notably symbols and lists, each @scheme[_datum]
|
||||
is typically a number, symbol, or boolean.
|
||||
|
||||
Multiple @scheme[_datum]s can be supplied for each clause, and the
|
||||
corresponding @scheme[_expr] is evaluated of any of the
|
||||
@scheme[_datum]s match.
|
||||
|
||||
@examples[
|
||||
(let ([v (random 6)])
|
||||
(printf "~a\n" v)
|
||||
(case v
|
||||
[(0) 'zero]
|
||||
[(1) 'one]
|
||||
[(2) 'two]
|
||||
[(3 4 5) 'many]))
|
||||
]
|
||||
|
||||
The last clause of a @scheme[case] form can use @scheme[else], just
|
||||
like @scheme[cond]:
|
||||
|
||||
@examples[
|
||||
(case (random 6)
|
||||
[(0) 'zero]
|
||||
[(1) 'one]
|
||||
[(2) 'two]
|
||||
[else 'many])
|
||||
]
|
||||
|
||||
For more general pattern matching, use @scheme[match], which is
|
||||
introduced in @secref["match"].
|
|
@ -4,7 +4,8 @@
|
|||
scheme/class
|
||||
"guide-utils.ss"
|
||||
|
||||
(for-label scheme/class))
|
||||
(for-label scheme/class
|
||||
scheme/trait))
|
||||
|
||||
@(define class-eval
|
||||
(let ([e (make-base-eval)])
|
||||
|
@ -13,8 +14,11 @@
|
|||
|
||||
@; FIXME: at some point, discuss classes vs. units vs. modules
|
||||
|
||||
|
||||
@title[#:tag "classes"]{Classes and Objects}
|
||||
|
||||
@margin-note{This section is based on a paper @cite["Flatt06"].}
|
||||
|
||||
A @scheme[class] expression denotes a first-class value,
|
||||
just like a @scheme[lambda] expression:
|
||||
|
||||
|
@ -68,13 +72,13 @@ The @scheme[size] initialization argument must be supplied via a named
|
|||
argument when instantiating the class through the @scheme[new] form:
|
||||
|
||||
@schemeblock[
|
||||
(new (class object% (init size) ...) [size 10])
|
||||
(new (class object% (init size) ....) [size 10])
|
||||
]
|
||||
|
||||
Of course, we can also name the class and its instance:
|
||||
|
||||
@schemeblock[
|
||||
(define fish% (class object% (init size) ...))
|
||||
(define fish% (class object% (init size) ....))
|
||||
(define charlie (new fish% [size 10]))
|
||||
]
|
||||
|
||||
|
@ -153,7 +157,7 @@ which brings the method name into scope for a direct call:
|
|||
With the @scheme[inherit] declaration, if @scheme[fish%] had not
|
||||
provided an @scheme[eat] method, an error would be signaled in the
|
||||
evaluation of the @scheme[class] form for @scheme[hungry-fish%]. In
|
||||
contrast, with @scheme[(send this ...)], an error would not be
|
||||
contrast, with @scheme[(send this ....)], an error would not be
|
||||
signaled until the @scheme[eat-more] method is called and the
|
||||
@scheme[send] form is evaluated. For this reason, @scheme[inherit] is
|
||||
preferred.
|
||||
|
@ -216,7 +220,7 @@ overridden method via a @scheme[super] call. For example, the
|
|||
@section[#:tag "initargs"]{Initialization Arguments}
|
||||
|
||||
Since @scheme[picky-fish%] declares no initialization arguments, any
|
||||
initialization values supplied in @scheme[(new picky-fish% ...)] are
|
||||
initialization values supplied in @scheme[(new picky-fish% ....)] are
|
||||
propagated to the superclass initialization, i.e., to @scheme[fish%].
|
||||
A subclass can supply additional initialization arguments for its
|
||||
superclass in a @scheme[super-new] call, and such initialization
|
||||
|
@ -300,7 +304,7 @@ For example, instead of forcing all fish classes to be derived from
|
|||
|
||||
@schemeblock[
|
||||
(define fish-interface (interface () get-size grow eat))
|
||||
(define fish% (class* object% (fish-interface) ...))
|
||||
(define fish% (class* object% (fish-interface) ....))
|
||||
]
|
||||
|
||||
If the definition of @scheme[fish%] does not include
|
||||
|
@ -327,7 +331,7 @@ new method or an overriding implementation.
|
|||
|
||||
Between the extremes of allowing arbitrary overriding and disallowing
|
||||
overriding entirely, the class system also supports Beta-style
|
||||
@defterm{augmentable} methods. A method
|
||||
@defterm{augmentable} methods @cite["Goldberg04"]. A method
|
||||
declared with @scheme[pubment] is like @scheme[public], but the method
|
||||
cannot be overridden in subclasses; it can be augmented only. A
|
||||
@scheme[pubment] method must explicitly invoke an augmentation (if any)
|
||||
|
@ -355,7 +359,7 @@ maps member keys to methods, fields, and initialization arguments.
|
|||
Recall the @scheme[hungry-fish%] @scheme[class] expression:
|
||||
|
||||
@schemeblock[
|
||||
(define hungry-fish% (class fish% ...
|
||||
(define hungry-fish% (class fish% ....
|
||||
(inherit eat)
|
||||
(define/public (eat-more fish1 fish2)
|
||||
(eat fish1) (eat fish2))))
|
||||
|
@ -389,15 +393,17 @@ cooperating classes:
|
|||
(let () ; create a local definition scope
|
||||
(define-member-name get-depth (generate-member-key))
|
||||
(define fish%
|
||||
(class ... (define my-depth ...)
|
||||
(define my-pond ...)
|
||||
(define/public (dive amt)
|
||||
(set! my-depth
|
||||
(min (+ my-depth amt)
|
||||
(send my-pond get-depth))))))
|
||||
(class ....
|
||||
(define my-depth ....)
|
||||
(define my-pond ....)
|
||||
(define/public (dive amt)
|
||||
(set! my-depth
|
||||
(min (+ my-depth amt)
|
||||
(send my-pond get-depth))))))
|
||||
(define pond%
|
||||
(class ... (define current-depth ...)
|
||||
(define/public (get-depth) current-depth)))
|
||||
(class ....
|
||||
(define current-depth ....)
|
||||
(define/public (get-depth) current-depth)))
|
||||
(values fish% pond%)))
|
||||
]
|
||||
|
||||
|
@ -414,4 +420,382 @@ A member-key value is primarily used with a
|
|||
@scheme[(member-name-key id)] captures the method key of @scheme[id]
|
||||
so that it can be communicated to a use of @scheme[define-member-name]
|
||||
in a different scope. This capability turns out to be useful for
|
||||
generalizing mixins (see mixins...).
|
||||
generalizing mixins, as discussed next.
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@section{Mixins}
|
||||
|
||||
Since @scheme[class] is an expression form instead of a top-level
|
||||
declaration as in Smalltalk and Java, a @scheme[class] form can be
|
||||
nested inside any lexical scope, including @scheme[lambda]. The result
|
||||
is a @deftech{mixin}, i.e., a class extension that is parameterized
|
||||
with respect to its superclass.
|
||||
|
||||
For example, we can parameterize the @scheme[picky-fish%] class over
|
||||
its superclass to define @scheme[picky-mixin]:
|
||||
|
||||
@schemeblock[
|
||||
(define (picky-mixin %)
|
||||
(class % (super-new)
|
||||
(define/override (grow amt) (super grow (* 3/4 amt)))))
|
||||
(define picky-fish% (picky-mixin fish%))
|
||||
]
|
||||
|
||||
Many small differences between Smalltalk-style classes and Scheme
|
||||
classes contribute to the effective use of mixins. In particular, the
|
||||
use of @scheme[define/override] makes explicit that
|
||||
@scheme[picky-mixin] expects a class with a @scheme[grow] method. If
|
||||
@scheme[picky-mixin] is applied to a class without a @scheme[grow]
|
||||
method, an error is signaled as soon as @scheme[picky-mixin] is
|
||||
applied.
|
||||
|
||||
Similarly, a use of @scheme[inherit] enforces a ``method existence''
|
||||
requirement when the mixin is applied:
|
||||
|
||||
@schemeblock[
|
||||
(define (hungry-mixin %)
|
||||
(class % (super-new)
|
||||
(inherit eat)
|
||||
(define/public (eat-more fish1 fish2)
|
||||
(eat fish1)
|
||||
(eat fish2))))
|
||||
]
|
||||
|
||||
The advantage of mixins is that we can easily combine them to create
|
||||
new classes whose implementation sharing does not fit into a
|
||||
single-inheritance hierarchy---without the ambiguities associated with
|
||||
multiple inheritance. Equipped with @scheme[picky-mixin] and
|
||||
@scheme[hungry-mixin], creating a class for a hungry, yet picky fish
|
||||
is straightforward:
|
||||
|
||||
@schemeblock[
|
||||
(define picky-hungry-fish%
|
||||
(hungry-mixin (picky-mixin fish%)))
|
||||
]
|
||||
|
||||
The use of keyword initialization arguments is critical for the easy
|
||||
use of mixins. For example, @scheme[picky-mixin] and
|
||||
@scheme[hungry-mixin] can augment any class with suitable @scheme[eat]
|
||||
and @scheme[grow] methods, because they do not specify initialization
|
||||
arguments and add none in their @scheme[super-new] expressions:
|
||||
|
||||
@schemeblock[
|
||||
(define person%
|
||||
(class object%
|
||||
(init name age)
|
||||
....
|
||||
(define/public (eat food) ....)
|
||||
(define/public (grow amt) ....)))
|
||||
(define child% (hungry-mixin (picky-mixin person%)))
|
||||
(define oliver (new child% [name "Oliver"][age 6]))
|
||||
]
|
||||
|
||||
Finally, the use of external names for class members (instead of
|
||||
lexically scoped identifiers) makes mixin use convenient. Applying
|
||||
@scheme[picky-mixin] to @scheme[person%] works because the names
|
||||
@scheme[eat] and @scheme[grow] match, without any a priori declaration
|
||||
that @scheme[eat] and @scheme[grow] should be the same method in
|
||||
@scheme[fish%] and @scheme[person%]. This feature is a potential
|
||||
drawback when member names collide accidentally; some accidental
|
||||
collisions can be corrected by limiting the scope external names, as
|
||||
discussed in @secref["extnames"].
|
||||
|
||||
@subsection{Mixins and Interfaces}
|
||||
|
||||
Using @scheme[implementation?], @scheme[picky-mixin] could require
|
||||
that its base class implements @scheme[grower-interface], which could
|
||||
be implemented by both @scheme[fish%] and @scheme[person%]:
|
||||
|
||||
@schemeblock[
|
||||
(define grower-interface (interface () grow))
|
||||
(define (picky-mixin %)
|
||||
(unless (implementation? % grower-interface)
|
||||
(error "picky-mixin: not a grower-interface class"))
|
||||
(class % ....))
|
||||
]
|
||||
|
||||
Another use of interfaces with a mixin is to tag classes generated by
|
||||
the mixin, so that instances of the mixin can be recognized. In other
|
||||
words, @scheme[is-a?] cannot work on a mixin represented as a
|
||||
function, but it can recognize an interface (somewhat like a
|
||||
@defterm{specialization interface}) that is consistently implemented
|
||||
by the mixin. For example, classes generated by @scheme[picky-mixin]
|
||||
could be tagged with @scheme[picky-interface], enabling the
|
||||
@scheme[is-picky?] predicate:
|
||||
|
||||
@schemeblock[
|
||||
(define picky-interface (interface ()))
|
||||
(define (picky-mixin %)
|
||||
(unless (implementation? % grower-interface)
|
||||
(error "picky-mixin: not a grower-interface class"))
|
||||
(class* % (picky-interface) ....))
|
||||
(define (is-picky? o)
|
||||
(is-a? o picky-interface))
|
||||
]
|
||||
|
||||
@subsection{The @scheme[mixin] Form}
|
||||
|
||||
To codify the @scheme[lambda]-plus-@scheme[class] pattern for
|
||||
implementing mixins, including the use of interfaces for the domain
|
||||
and range of the mixin, the class system provides a @scheme[mixin]
|
||||
macro:
|
||||
|
||||
@specform[
|
||||
(mixin (interface-expr ...) (interface-expr ...)
|
||||
decl-or-expr ...)
|
||||
]
|
||||
|
||||
The first set of @scheme[interface-expr]s determines the domain of the
|
||||
mixin, and the second set determines the range. That is, the expansion
|
||||
is a function that tests whether a given base class implements the
|
||||
first sequence of @scheme[interface-expr]s and produces a class that
|
||||
implements the second sequence of @scheme[interface-expr]s. Other
|
||||
requirements, such as the presence of @scheme[inherit]ed methods in
|
||||
the superclass, are then checked for the @scheme[class] expansion of
|
||||
the @scheme[mixin] form.
|
||||
|
||||
Mixins not only override methods and introduce public methods, they
|
||||
can also augment methods, introduce augment-only methods, add an
|
||||
overrideable augmentation, and add an augmentable override --- all of
|
||||
the things that a class can do (see @secref["inner"]).
|
||||
|
||||
|
||||
@subsection[#:tag "parammixins"]{Parameterized Mixins}
|
||||
|
||||
As noted in @secref["extnames"], external names can be bound with
|
||||
@scheme[define-member-name]. This facility allows a mixin to be
|
||||
generalized with respect to the methods that it defines and uses. For
|
||||
example, we can parameterize @scheme[hungry-mixin] with respect to the
|
||||
external member key for @scheme[eat]:
|
||||
|
||||
@schemeblock[
|
||||
(define (make-hungry-mixin eat-method-key)
|
||||
(define-member-name eat eat-method-key)
|
||||
(mixin () () (super-new)
|
||||
(inherit eat)
|
||||
(define/public (eat-more x y) (eat x) (eat y))))
|
||||
]
|
||||
|
||||
To obtain a particular hungry-mixin, we must apply this function to a
|
||||
member key that refers to a suitable
|
||||
@scheme[eat] method, which we can obtain using @scheme[member-name-key]:
|
||||
|
||||
@schemeblock[
|
||||
((make-hungry-mixin (member-name-key eat))
|
||||
(class object% .... (define/public (eat x) 'yum)))
|
||||
]
|
||||
|
||||
Above, we apply @scheme[hungry-mixin] to an anonymous class that provides
|
||||
@scheme[eat], but we can also combine it with a class that provides
|
||||
@scheme[chomp], instead:
|
||||
|
||||
@schemeblock[
|
||||
((make-hungry-mixin (member-name-key chomp))
|
||||
(class object% .... (define/public (chomp x) 'yum)))
|
||||
]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@section{Traits}
|
||||
|
||||
A @defterm{trait} is similar to a mixin, in that it encapsulates a set
|
||||
of methods to be added to a class. A trait is different from a mixin
|
||||
in that its individual methods can be manipulated with trait operators
|
||||
such as @scheme[trait-sum] (merge the methods of two traits), @scheme[trait-exclude]
|
||||
(remove a method from a trait), and @scheme[trait-alias] (add a copy of a
|
||||
method with a new name; do not redirect any calls to the old name).
|
||||
|
||||
The practical difference between mixins and traits is that two traits
|
||||
can be combined, even if they include a common method and even if
|
||||
neither method can sensibly override the other. In that case, the
|
||||
programmer must explicitly resolve the collision, usually by aliasing
|
||||
methods, excluding methods, and merging a new trait that uses the
|
||||
aliases.
|
||||
|
||||
Suppose our @scheme[fish%] programmer wants to define two class
|
||||
extensions, @scheme[spots] and @scheme[stripes], each of which
|
||||
includes a @scheme[get-color] method. The fish's spot color should not
|
||||
override the stripe color nor vice-versa; instead, a
|
||||
@scheme[spots+stripes-fish%] should combine the two colors, which is
|
||||
not possible if @scheme[spots] and @scheme[stripes] are implemented as
|
||||
plain mixins. If, however, @scheme[spots] and @scheme[stripes] are
|
||||
implemented as traits, they can be combined. First, we alias
|
||||
@scheme[get-color] in each trait to a non-conflicting name. Second,
|
||||
the @scheme[get-color] methods are removed from both and the traits
|
||||
with only aliases are merged. Finally, the new trait is used to create
|
||||
a class that introduces its own @scheme[get-color] method based on the
|
||||
two aliases, producing the desired @scheme[spots+stripes] extension.
|
||||
|
||||
@subsection{Traits as Sets of Mixins}
|
||||
|
||||
One natural approach to implementing traits in PLT Scheme is as a set
|
||||
of mixins, with one mixin per trait method. For example, we might
|
||||
attempt to define the spots and stripes traits as follows, using
|
||||
association lists to represent sets:
|
||||
|
||||
@schemeblock[
|
||||
(define spots-trait
|
||||
(list (cons 'get-color
|
||||
(lambda (%) (class % (super-new)
|
||||
(define/public (get-color)
|
||||
'black))))))
|
||||
(define stripes-trait
|
||||
(list (cons 'get-color
|
||||
(lambda (%) (class % (super-new)
|
||||
(define/public (get-color)
|
||||
'red))))))
|
||||
]
|
||||
|
||||
A set representation, such as the above, allows @scheme[trait-sum] and
|
||||
@scheme[trait-exclude] as simple manipulations; unfortunately, it does
|
||||
not support the @scheme[trait-alias] operator. Although a mixin can be
|
||||
duplicated in the association list, the mixin has a fixed method name,
|
||||
e.g., @scheme[get-color], and mixins do not support a method-rename
|
||||
operation. To support @scheme[trait-alias], we must parameterize the
|
||||
mixins over the external method name in the same way that @scheme[eat]
|
||||
was parameterized in @secref["parammixins"].
|
||||
|
||||
To support the @scheme[trait-alias] operation, @scheme[spots-trait]
|
||||
should be represented as:
|
||||
|
||||
@schemeblock[
|
||||
(define spots-trait
|
||||
(list (cons (member-name-key get-color)
|
||||
(lambda (get-color-key %)
|
||||
(define-member-name get-color get-color-key)
|
||||
(class % (super-new)
|
||||
(define/public (get-color) 'black))))))
|
||||
]
|
||||
|
||||
When the @scheme[get-color] method in @scheme[spots-trait] is aliased
|
||||
to @scheme[get-trait-color] and the @scheme[get-color] method is
|
||||
removed, the resulting trait is the same as
|
||||
|
||||
@schemeblock[
|
||||
(list (cons (member-name-key get-trait-color)
|
||||
(lambda (get-color-key %)
|
||||
(define-member-name get-color get-color-key)
|
||||
(class % (super-new)
|
||||
(define/public (get-color) 'black)))))
|
||||
]
|
||||
|
||||
To apply a trait @scheme[_T] to a class @scheme[_C] and obtain a derived
|
||||
class, we use @scheme[((trait->mixin _T) _C)]. The @scheme[trait->mixin]
|
||||
function supplies each mixin of @scheme[_T] with the key for the mixin's
|
||||
method and a partial extension of @scheme[_C]:
|
||||
|
||||
@schemeblock[
|
||||
(define ((trait->mixin T) C)
|
||||
(foldr (lambda (m %) ((cdr m) (car m) %)) C T))
|
||||
]
|
||||
|
||||
Thus, when the trait above is combined with other traits and then
|
||||
applied to a class, the use of @scheme[get-color] becomes a reference
|
||||
to the external name @scheme[get-trait-color].
|
||||
|
||||
@subsection{Inherit and Super in Traits}
|
||||
|
||||
This first implementation of traits supports @scheme[trait-alias], and it
|
||||
supports a trait method that calls itself, but it does not support
|
||||
trait methods that call each other. In particular, suppose that a spot-fish's
|
||||
market value depends on the color of its spots:
|
||||
|
||||
@schemeblock[
|
||||
(define spots-trait
|
||||
(list (cons (member-name-key get-color) ....)
|
||||
(cons (member-name-key get-price)
|
||||
(lambda (get-price %) ....
|
||||
(class % ....
|
||||
(define/public (get-price)
|
||||
.... (get-color) ....))))))
|
||||
]
|
||||
|
||||
In this case, the definition of @scheme[spots-trait] fails, because
|
||||
@scheme[get-color] is not in scope for the @scheme[get-price]
|
||||
mixin. Indeed, depending on the order of mixin application when the
|
||||
trait is applied to a class, the @scheme[get-color] method may not be
|
||||
available when @scheme[get-price] mixin is applied to the class.
|
||||
Therefore adding an @scheme[(inherit get-color)] declaration to the
|
||||
@scheme[get-price] mixin does not solve the problem.
|
||||
|
||||
One solution is to require the use of @scheme[(send this get-color)] in
|
||||
methods such as @scheme[get-price]. This change works because
|
||||
@scheme[send] always delays the method lookup until the method call is
|
||||
evaluated. The delayed lookup is more expensive than a direct call,
|
||||
however. Worse, it also delays checking whether a @scheme[get-color] method
|
||||
even exists.
|
||||
|
||||
A second, effective, and efficient solution is to change the encoding
|
||||
of traits. Specifically, we represent each method as a pair of mixins:
|
||||
one that introduces the method and one that implements it. When a
|
||||
trait is applied to a class, all of the method-introducing mixins are
|
||||
applied first. Then the method-implementing mixins can use
|
||||
@scheme[inherit] to directly access any introduced method.
|
||||
|
||||
@schemeblock[
|
||||
(define spots-trait
|
||||
(list (list (local-member-name-key get-color)
|
||||
(lambda (get-color get-price %) ....
|
||||
(class % ....
|
||||
(define/public (get-color) (void))))
|
||||
(lambda (get-color get-price %) ....
|
||||
(class % ....
|
||||
(define/override (get-color) 'black))))
|
||||
(list (local-member-name-key get-price)
|
||||
(lambda (get-price get-color %) ....
|
||||
(class % ....
|
||||
(define/public (get-price) (void))))
|
||||
(lambda (get-color get-price %) ....
|
||||
(class % ....
|
||||
(inherit get-color)
|
||||
(define/override (get-price)
|
||||
.... (get-color) ....))))))
|
||||
]
|
||||
|
||||
With this trait encoding, @scheme[trait-alias] adds a new method with
|
||||
a new name, but it does not change any references to the old method.
|
||||
|
||||
@subsection{The @scheme[trait] Form}
|
||||
|
||||
The general-purpose trait pattern is clearly too complex for a
|
||||
programmer to use directly, but it is easily codified in a
|
||||
@scheme[trait] macro:
|
||||
|
||||
@specform[
|
||||
(trait trait-clause ...)
|
||||
]
|
||||
|
||||
The @scheme[id]s in the optional @scheme[inherit] clause are available for direct
|
||||
reference in the method @scheme[expr]s, and they must be supplied
|
||||
either by other traits or the base class to which
|
||||
the trait is ultimately applied.
|
||||
|
||||
Using this form in conjunction with trait operators such as
|
||||
@scheme[trait-sum], @scheme[trait-exclude], @scheme[trait-alias], and
|
||||
@scheme[trait->mixin], we can implement @scheme[spots-trait] and
|
||||
@scheme[stripes-trait] as desired.
|
||||
|
||||
@schemeblock[
|
||||
(define spots-trait
|
||||
(trait
|
||||
(define/public (get-color) 'black)
|
||||
(define/public (get-price) ... (get-color) ...)))
|
||||
|
||||
(define stripes-trait
|
||||
(trait
|
||||
(define/public (get-color) 'red)))
|
||||
|
||||
(define spots+stripes-trait
|
||||
(trait-sum
|
||||
(trait-exclude (trait-alias spots-trait
|
||||
get-color get-spots-color)
|
||||
get-color)
|
||||
(trait-exclude (trait-alias stripes-trait
|
||||
get-color get-stripes-color)
|
||||
get-color)
|
||||
(trait
|
||||
(inherit get-spots-color get-stripes-color)
|
||||
(define/public (get-color)
|
||||
.... (get-spots-color) .... (get-stripes-color) ....))))
|
||||
]
|
||||
|
|
|
@ -88,3 +88,5 @@ form, a @scheme[_thing] is either an identifier or a keyword.
|
|||
@include-section["begin.scrbl"]
|
||||
@include-section["set.scrbl"]
|
||||
@include-section["quote.scrbl"]
|
||||
@include-section["qq.scrbl"]
|
||||
@include-section["case.scrbl"]
|
||||
|
|
|
@ -35,38 +35,23 @@ precise details to @|MzScheme| and other reference manuals.
|
|||
|
||||
@include-section["io.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@include-section["class.scrbl"]
|
||||
|
||||
@include-section["regexp.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "control"]{Exceptions and Control}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@include-section["for.scrbl"]
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "regexp"]{Regular-Expression Matching@aux-elem{ (Regexps)}}
|
||||
|
||||
@include-section["match.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "match"]{Pattern Matching}
|
||||
|
||||
@subsection{Simple Dispatch: @scheme[case]}
|
||||
|
||||
The @scheme[case] form dispatches to a clause by matching the result
|
||||
of an expression to the values for the clause:
|
||||
|
||||
@specform[(case [(_datum ...+) expr ...+]
|
||||
...)]
|
||||
@include-section["class.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@include-section["qq.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "units"]{Units (Higher-Order Modules)}
|
||||
@section[#:tag "units"]{Units@aux-elem{ (Components)}}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
@ -79,12 +64,11 @@ there is a parameter that determines the default destination for
|
|||
printed output.
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@include-section["macros.scrbl"]
|
||||
@include-section["namespaces.scrbl"]
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@include-section["namespaces.scrbl"]
|
||||
|
||||
@include-section["macros.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "reader"]{Reader Extension}
|
||||
|
@ -103,38 +87,15 @@ printed output.
|
|||
@; ----------------------------------------------------------------------
|
||||
@include-section["performance.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "ffi"]{Foreign-Function Interface@aux-elem{ (FFI)}}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "scripts"]{Scripts}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "mred"]{Graphical User Interfaces@aux-elem{ (GUIs)}}
|
||||
|
||||
@deftech{MrEd} is both a library and an executable. As a library,
|
||||
@scheme[(lib "mred/mred.ss")] provides class, interface, and function
|
||||
bindings for writing GUI programs. An an executable, @exec{mred}
|
||||
substitutes for @exec{mzscheme} to run MrEd programs. (The
|
||||
@exec{mzscheme} executable cannot run MrEd programs, because
|
||||
@exec{mzscheme} does not include primitive GUI support, and because
|
||||
some operating systems distinguish GUI applications from command-line
|
||||
applications.)
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "tools"]{More Tools}
|
||||
|
||||
In the @seclink["intro"]{introduction}, we mentioned that PLT Scheme
|
||||
includes more tools besides DrScheme and MzScheme:
|
||||
@section{Configuration and Compilation}
|
||||
|
||||
@itemize{
|
||||
|
||||
@tool["MrEd"]{extends MzScheme with graphical user interface (GUI)
|
||||
and drawing primitives}
|
||||
|
||||
@tool["Setup PLT"]{a command-line tool for installation tasks}
|
||||
@tool["setup-plt"]{a command-line tool for installation tasks}
|
||||
|
||||
@tool["planet"]{a command-line tool for managing packages that are
|
||||
normally downloaded automatically, on demand}
|
||||
|
@ -147,5 +108,45 @@ includes more tools besides DrScheme and MzScheme:
|
|||
}
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section{More Libraries}
|
||||
|
||||
@italic{@secref[#:doc '(lib "scribblings/gui/gui.scrbl") "top"]} describes the
|
||||
PLT Scheme graphics toolbox, whose core is implemented by the MrEd
|
||||
executable.
|
||||
|
||||
@italic{@secref[#:doc '(lib "scribblings/foreign/foreign.scrbl")
|
||||
"top"]} describes tools for using Scheme to access libraries that are
|
||||
normally used by C programs.
|
||||
|
||||
@italic{@secref[#:doc '(lib "web-server/docs/reference/web-reference.scrbl")
|
||||
"top"]} describes the PLT Scheme web server, which supports servlets
|
||||
implemented in Scheme.
|
||||
|
||||
@italic{@secref[#:doc '(lib "scribblings/start/start.scrbl") "top"]} provides
|
||||
links to documentation for many other libraries distributed with PLT
|
||||
Scheme or installed on your system.
|
||||
|
||||
@link["http://planet.plt-scheme.org/"]{@|PLaneT|} offers even more
|
||||
downloadable packages contributed by PLT Scheme users.
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@(bibliography
|
||||
|
||||
(bib-entry #:key "Goldberg04"
|
||||
#:author "David Goldberg, Robert Bruce Findler, and Matthew Flatt"
|
||||
#:title "Super and Inner---Together at Last!"
|
||||
#:location "Object-Oriented Programming, Languages, Systems, and Applications"
|
||||
#:date "2004"
|
||||
#:url "http://www.cs.utah.edu/plt/publications/oopsla04-gff.pdf")
|
||||
|
||||
(bib-entry #:key "Flatt06"
|
||||
#:author "Matthew Flatt, Robert Bruce Findler, and Matthias Felleisen"
|
||||
#:title "Scheme with Classes, Mixins, and Traits (invited tutorial)"
|
||||
#:location "Asian Symposium on Programming Languages and Systems"
|
||||
#:date "2006")
|
||||
|
||||
|
||||
)
|
||||
|
||||
@index-section[]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
@require[scribble/eval]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@title[#:tag "macros" #:style 'toc]{Syntactic Extension@aux-elem{ (Macros)}}
|
||||
@title[#:tag "macros" #:style 'toc]{Macros}
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
|
|
12
collects/scribblings/guide/match.scrbl
Normal file
12
collects/scribblings/guide/match.scrbl
Normal file
|
@ -0,0 +1,12 @@
|
|||
#lang scribble/doc
|
||||
@require[scribble/manual]
|
||||
@require[scribble/eval]
|
||||
@require["guide-utils.ss"]
|
||||
@require[(for-label scheme/match)]
|
||||
|
||||
@title[#:tag "match"]{Pattern Matching}
|
||||
|
||||
The @scheme[match] form supports pattern matching on arbitrary Scheme
|
||||
values, as opposed to functions like @scheme[regexp-match] that
|
||||
compare regular expressions to byte and character sequences (see
|
||||
@secref["regexp"]).
|
|
@ -3,24 +3,22 @@
|
|||
@require[scribble/eval]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@title{Quasiquoting}
|
||||
@(define qq (scheme quasiquote))
|
||||
@(define uq (scheme unquote))
|
||||
|
||||
[Explain why...]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Escapes: @scheme[quasiquote], @scheme[unquote], and @scheme[unquote-splicing]}
|
||||
@title{Quasiquoting: @scheme[quasiquote] and @schemevalfont{`}}
|
||||
|
||||
The @scheme[quasiquote] form is similar to @scheme[quote]:
|
||||
|
||||
@specform[(#,(schemekeywordfont "quasiquote") datum)]
|
||||
@specform[(#,qq datum)]
|
||||
|
||||
However, for each @scheme[(#,(schemekeywordfont "unquote") _expr)]
|
||||
However, for each @scheme[(#,uq _expr)]
|
||||
that appears within the @scheme[_datum], the @scheme[_expr] is
|
||||
evaluated to produce a value that takes the place of the
|
||||
@scheme[unsyntax] sub-form.
|
||||
@scheme[unquote] sub-form.
|
||||
|
||||
@examples[
|
||||
(eval:alts (#,(schemekeywordfont "quasiquote") (1 2 (#,(schemekeywordfont "unquote") (+ 1 2)) (#,(schemekeywordfont "unquote") (- 5 1))))
|
||||
(eval:alts (#,qq (1 2 (#,uq (+ 1 2)) (#,uq (- 5 1))))
|
||||
`(1 2 ,(+ 1 2), (- 5 1)))
|
||||
]
|
||||
|
||||
|
@ -31,7 +29,7 @@ either a list or a vector. As the name suggests, the resulting list
|
|||
is spliced into the context of its use.
|
||||
|
||||
@examples[
|
||||
(eval:alts (#,(schemekeywordfont "quasiquote") (1 2 (#,(schemekeywordfont "unquote-splicing") (list (+ 1 2) (- 5 1))) 5))
|
||||
(eval:alts (#,qq (1 2 (#,(scheme unquote-splicing) (list (+ 1 2) (- 5 1))) 5))
|
||||
`(1 2 ,@(list (+ 1 2) (- 5 1)) 5))
|
||||
]
|
||||
|
||||
|
@ -41,6 +39,25 @@ effectively cancels one layer of @scheme[unquote] and
|
|||
@scheme[unquote-splicing] forms, so that a second @scheme[unquote]
|
||||
or @scheme[unquote-splicing] is needed.
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Abbreviating with @schememetafont{`}, @schememetafont{,}, and @schememetafont[",@"]}
|
||||
@examples[
|
||||
(eval:alts (#,qq (1 2 (#,qq (#,uq (+ 1 2)
|
||||
(#,uq (#,uq (- 5 1)))))))
|
||||
`(1 2 (,(string->uninterned-symbol "quasiquote")
|
||||
(,(string->uninterned-symbol "unquote") (+ 1 2))
|
||||
(,(string->uninterned-symbol "unquote") 4))))
|
||||
]
|
||||
|
||||
The evaluation above will not actually print as shown. Instead, the
|
||||
shorthand form of @scheme[quasiquote] and @scheme[unquote] will be
|
||||
used: @litchar{`} (i.e., a backquote) and @litchar{,} (i.e., a comma).
|
||||
The same shorthands can be used in expressions:
|
||||
|
||||
@examples[
|
||||
`(1 2 `(,(+ 1 2) ,,(- 5 1)))
|
||||
]
|
||||
|
||||
The shorthand for of @scheme[unquote-splicing] is @litchar[",@"]:
|
||||
|
||||
@examples[
|
||||
`(1 2 ,@(list (+ 1 2) (- 5 1)))
|
||||
]
|
||||
|
|
6
collects/scribblings/guide/regexp.scrbl
Normal file
6
collects/scribblings/guide/regexp.scrbl
Normal file
|
@ -0,0 +1,6 @@
|
|||
#lang scribble/doc
|
||||
@require[scribble/manual]
|
||||
@require[scribble/eval]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@title[#:tag "regexp"]{Regular Expressions}
|
|
@ -85,7 +85,7 @@ lists that prints as @schemeresult[((1) (2) (3))]. The @scheme[quote]
|
|||
form does exactly that:
|
||||
|
||||
@interaction[
|
||||
(eval:alts (#, @scheme[quote] (1 2 3)) '(1 2 3))
|
||||
(eval:alts (#, @scheme[quote] ((1) (2) (3))) '((1) (2) (3)))
|
||||
(eval:alts (#, @scheme[quote] ("red" "green" "blue")) '("red" "green" "blue"))
|
||||
(eval:alts (#, @scheme[quote] ()) '())
|
||||
]
|
||||
|
@ -99,7 +99,7 @@ not:
|
|||
(eval:alts (#, @scheme[quote] (0 #, @schemeparenfont{.} (1 . 2))) '(0 . (1 . 2)))
|
||||
]
|
||||
|
||||
Naturally, lists can be nested:
|
||||
Naturally, lists of any kind can be nested:
|
||||
|
||||
@interaction[
|
||||
(list (list 1 2 3) 5 (list "a" "b" "c"))
|
||||
|
|
62
collects/scribblings/reference/info.scrbl
Normal file
62
collects/scribblings/reference/info.scrbl
Normal file
|
@ -0,0 +1,62 @@
|
|||
#lang scribble/doc
|
||||
@(require "mz.ss"
|
||||
(for-label string-constants/string-constant
|
||||
setup/getinfo))
|
||||
|
||||
@title[#:tag "info.ss"]{@filepath{info.ss} File Format}
|
||||
|
||||
In each @tech{collection}, a special module file @filepath{info.ss}
|
||||
provides general information about a collection for use by various
|
||||
tools. For example, an @filepath{info.ss} file specifies how to build
|
||||
the documentation for a collection, and it lists plug-in tools for
|
||||
DrScheme that the collection provides.
|
||||
|
||||
Although an @filepath{info.ss} file contains a module declaration, the
|
||||
declaration has a highly constrained form. It must match the following
|
||||
grammar of @scheme[_info-module]:
|
||||
|
||||
@schemegrammar*[
|
||||
#:literals (info lib infotab/setup quote quasiquote
|
||||
cons car cdr list list* reverse append
|
||||
string-append path->string build-path
|
||||
collection-path
|
||||
system-library-subpath
|
||||
string-constant)
|
||||
[info-module (module info intotab-mod-path
|
||||
(define id info-expr)
|
||||
...)]
|
||||
[intotab-mod-path (lib "infotab.ss" "setup")
|
||||
infotab/setup]
|
||||
[info-expr (quote datum)
|
||||
(quasiquote datum)
|
||||
(info-primitive info-expr ...)
|
||||
id
|
||||
string
|
||||
number
|
||||
boolean
|
||||
(string-constant identifier)]
|
||||
[info-primitive cons car cdr list
|
||||
list* reverse append
|
||||
string-append
|
||||
path->string build-path collection-path
|
||||
system-library-subpath]
|
||||
]
|
||||
|
||||
For example, the following declaration could be the @filepath{info.ss}
|
||||
library of the @filepath{help} collection. It contains definitions for
|
||||
three info tags, @scheme[name], @scheme[mzscheme-launcher-libraries], and
|
||||
@scheme[mzscheme-launcher-names].
|
||||
|
||||
@schemeblock[
|
||||
(module info setup/infotab
|
||||
(define name "Help")
|
||||
(define mzscheme-launcher-libraries '("help.ss"))
|
||||
(define mzscheme-launcher-names '("PLT Help")))
|
||||
]
|
||||
|
||||
The @scheme[name] tag is required for @exec{setup-plt} to recognize
|
||||
the collection and compile its files to bytecode. Similarly, an
|
||||
@filepath{info.ss} file in a sub-directory of a collection causes the
|
||||
sub-directory's files to be compiled.
|
||||
|
||||
See also @scheme[get-info] from @schememodname[setup/getinfo].
|
|
@ -5,8 +5,6 @@
|
|||
|
||||
@title{Init Libraries}
|
||||
|
||||
See also @secref["init-actions"].
|
||||
|
||||
@defmodule*/no-declare[(scheme/init)]{The @schememodname[scheme/init]
|
||||
library is the default start-up library for MzScheme. It re-exports
|
||||
the @schememodname[scheme] and @schememodname[scheme/help] libraries,
|
||||
|
|
|
@ -61,14 +61,14 @@ where @schememodname[scheme] includes all of
|
|||
(bib-entry #:key "Gasbichler02"
|
||||
#:title "Processes vs. User-Level Threads in Scsh"
|
||||
#:author "Martin Gasbichler and Michael Sperber"
|
||||
#:date 2002
|
||||
#:date "2002"
|
||||
#:location "Workshop on Scheme and Functional Programming")
|
||||
|
||||
(bib-entry #:key "Gunter95"
|
||||
#:author "Carl Gunter, Didier Remy, and Jon Rieke"
|
||||
#:title "A Generalization of Exceptions and Control in ML-like Languages"
|
||||
#:location "Functional Programming Languages and Computer Architecture"
|
||||
#:date 1995)
|
||||
#:date "1995")
|
||||
|
||||
(bib-entry #:key "Hieb90"
|
||||
#:author "Robert Hieb and R. Kent Dybvig"
|
||||
|
@ -92,7 +92,7 @@ where @schememodname[scheme] includes all of
|
|||
#:author "Ken Shan"
|
||||
#:title "Shift to Control"
|
||||
#:location "Workshop on Scheme and Functional Programming"
|
||||
#:date 2004)
|
||||
#:date "2004")
|
||||
|
||||
(bib-entry #:key "Sitaram90"
|
||||
#:author "Dorai Sitaram"
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
|
||||
@include-section["startup.scrbl"]
|
||||
@include-section["collects.scrbl"]
|
||||
@include-section["info.scrbl"]
|
||||
@include-section["help.scrbl"]
|
||||
@include-section["init.scrbl"]
|
||||
|
|
|
@ -86,6 +86,10 @@ the exit status is @scheme[0] or determined by a call to
|
|||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@include-section["init.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@section{Command Line}
|
||||
|
||||
The MzScheme and MrEd executables recognize the following command-line
|
||||
|
|
Loading…
Reference in New Issue
Block a user