work on guide, and fix problems with scribble/eval

svn: r8250
This commit is contained in:
Matthew Flatt 2008-01-07 21:47:22 +00:00
parent 8f0f4fcdf9
commit 343308481a
26 changed files with 688 additions and 152 deletions

View File

@ -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)])]

View File

@ -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 " "

View File

@ -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{

View File

@ -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"].

View File

@ -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{

View File

@ -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.

View File

@ -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

View File

@ -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)]

View File

@ -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

View File

@ -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{

View File

@ -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.

View File

@ -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

View 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"].

View File

@ -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) ....))))
]

View File

@ -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"]

View File

@ -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[]

View File

@ -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[]

View 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"]).

View File

@ -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)))
]

View File

@ -0,0 +1,6 @@
#lang scribble/doc
@require[scribble/manual]
@require[scribble/eval]
@require["guide-utils.ss"]
@title[#:tag "regexp"]{Regular Expressions}

View File

@ -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"))

View 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].

View File

@ -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,

View File

@ -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"

View File

@ -7,5 +7,5 @@
@include-section["startup.scrbl"]
@include-section["collects.scrbl"]
@include-section["info.scrbl"]
@include-section["help.scrbl"]
@include-section["init.scrbl"]

View File

@ -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