370 lines
12 KiB
Plaintext
370 lines
12 KiB
Plaintext
_The Father Time Language (FrTime)_
|
|
|
|
The `frtime' collection contains the implementation of FrTime, a
|
|
language that supports declarative construction of reactive systems
|
|
through signals, or time-varying values. Signals are classified as
|
|
either behaviors, which have a value at any point in (conceptually
|
|
continuous) time, or events, which are streams of discrete
|
|
occurrences. Unlike (for example) boxes, the time-varying nature of
|
|
signals propagates automatically to expressions in which they are
|
|
used.
|
|
|
|
To interact with FrTime, set the language level to FrTime. You can
|
|
also make FrTime the language for a module:
|
|
|
|
(module <module-name> frtime/frtime
|
|
<module-body>)
|
|
|
|
For the animation library and demo programs, set the language level
|
|
to (module ...), open the file, and execute. The demos are perhaps
|
|
the best way to learn about FrTime.
|
|
|
|
Note that FrTime is experimental, and various aspects of it may change
|
|
significantly, though we will try our best to maintain backwards
|
|
compatibility.
|
|
|
|
_Primitive Signals_
|
|
|
|
> seconds : behavior[num]
|
|
|
|
This behavior updates approximately every second with the value of
|
|
(current-seconds).
|
|
|
|
> milliseconds : behavior[num]
|
|
|
|
This behavior updates approximately every 20 milliseconds with the
|
|
value of (current-milliseconds). Future versions of FrTime will
|
|
provide an interface through which the programmer can create timers
|
|
with arbitrary update frequencies.
|
|
|
|
_Creating New Signals_
|
|
|
|
> (new-cell [behavior]) -> cell (a special behavior)
|
|
|
|
The returned cell can be used as a behavior; initially its value is
|
|
determined by the optional behavior given to the constructor
|
|
(default is <undefined>). For example, (new-cell seconds) behaves
|
|
like _seconds_.
|
|
|
|
> (set-cell! cell behavior) -> void
|
|
|
|
This procedure changes the value of the cell to that of the new
|
|
behavior.
|
|
|
|
> (event-receiver) -> event-rcvr (a special event source)
|
|
|
|
The returned value can be used as an event source. Specifically, it
|
|
emits an event occurrence whenever it is used as the first argument
|
|
to the following procedure:
|
|
|
|
> (send-event event-rcvr any) -> void
|
|
|
|
Emits the second argument as an occurrence on the given event source.
|
|
|
|
_Signal Processors_
|
|
|
|
> (value-now behavior[a]) -> a
|
|
|
|
This procedure projects the current value of the given behavior.
|
|
|
|
> (delay-by behavior[a] behavior[num]) -> behavior[a]
|
|
|
|
This procedure delays the given behavior by the given number of
|
|
milliseconds (which need not be constant).
|
|
|
|
> (integral behavior[num] {behavior[num] = 20}) -> behavior[num]
|
|
|
|
Computes a numeric approximation of the integral of the first
|
|
argument with respect to time, at a minimum rate given by the second
|
|
argument (interpreted in milliseconds). This procedure will probably
|
|
be rewritten soon.
|
|
|
|
> (derivative behavior[num]) -> behavior[num]
|
|
|
|
Computes a numeric approximation of the derivative of the first
|
|
argument with respect to time. This procedure needs to be
|
|
rewritten.
|
|
|
|
> (map-e proc event) -> event
|
|
> (event . ==> . proc) -> event
|
|
|
|
Returns an event source isomorphic to the given one, except that
|
|
each occurrence is the result of applying the given procedure to the
|
|
input event occurrence.
|
|
|
|
> (filter-e pred event) -> event
|
|
> (event . =#> . pred) -> event
|
|
|
|
Returns a filtered version of the given event source. Only
|
|
occurrences that satisfy the given predicate survive.
|
|
|
|
> (merge-e event ...) -> event
|
|
|
|
Merges all of the input event sources into a single event source.
|
|
|
|
> (once-e event) -> event
|
|
|
|
Returns an event source that carries only the first occurrence of the
|
|
argument event source. (The rest are filtered out.)
|
|
|
|
> (changes behavior) -> event
|
|
|
|
Returns an event source which occurs each time the argument behavior
|
|
changes. The value of the occurrence is the behavior's new value.
|
|
|
|
> (hold event [init]) -> behavior
|
|
|
|
Constructs a behavior from a given initial value (defaults to
|
|
<undefined>) and an event source. The value of the behavior is the
|
|
value of the most recent event occurrence.
|
|
|
|
> (switch event[behavior] [behavior]) -> behavior
|
|
|
|
Returns a behavior that "switches" each time the argument event
|
|
occurs. The second argument is an optional initializer.
|
|
|
|
> (accum-e event[a -> a] a) -> event[a]
|
|
|
|
Constructs an event source by accumulating changes (carried by the
|
|
given event source) over an initial value.
|
|
|
|
> (accum-b event[a -> a] a) -> behavior[a]
|
|
|
|
Combines functionality of accum-e and hold to construct a behavior.
|
|
(accum-b ev init) = (hold init (accum-e ev init)).
|
|
|
|
> (collect-e event[a] b (a b -> b)) -> event[b]
|
|
|
|
Like accum-e, except the transformer function is fixed and is applied
|
|
to the current accumulator and the event occurrence.
|
|
|
|
> (collect-b event[a] b (a b -> b)) -> behavior[b]
|
|
|
|
collect-b : collect-e :: accum-b : accum-e
|
|
|
|
> (when-e behavior) -> event
|
|
|
|
The returned event source carries an occurrence each time the argument
|
|
behavior changes from false to true (non-false).
|
|
|
|
> (<proc> behavior ...) -> behavior
|
|
|
|
FrTime provides "lifted" versions of most of MzScheme. This means
|
|
that these procedures may be applied to behaviors, and the result
|
|
automatically recomputes whenever any of the arguments changes.
|
|
|
|
_Special Syntax for FrTime_
|
|
|
|
> (if boolean-behavior then-expr else-expr) SYNTAX
|
|
|
|
FrTime permits the use of behaviors in conditional statements. By
|
|
definition, if the condition is <undefined>, then the result is also
|
|
<undefined>. Otherwise, the expression reflects the branch
|
|
currently selected by the condition. FrTime also provides 'cond',
|
|
'and', 'or', and 'case'.
|
|
|
|
> (snapshot (var ...) expr) SYNTAX
|
|
|
|
This projects the current values of the named variables within the
|
|
given expression.
|
|
|
|
> (require (lifted module-spec proc-name ...) ...) SYNTAX
|
|
> (require (lifted:nonstrict module-spec proc-name ...) ...) SYNTAX
|
|
> (require (as-is module-spec proc-name ...) ...) SYNTAX
|
|
> (require (as-is:unchecked module-spec proc-name ...) ...) SYNTAX
|
|
|
|
FrTime provides several new 'require' forms, which can be used to
|
|
import optionally modified definitions from existing libraries. The
|
|
'lifted' form takes a module specification and names of any number of
|
|
primitive procedures. The imported versions of the primitives can be
|
|
applied to behaviors. The 'lifted:nonstrict' form is similar, except
|
|
that, when given <undefined> arguments, FrTime will still perform the
|
|
application, instead of simply forcing the output value to be
|
|
<undefined>.
|
|
|
|
The 'as-is' forms do not lift imported procedures, so these should not
|
|
generally be used with signals. The 'unchecked' version permits
|
|
application to signals, while the plain 'as-is' always reports an
|
|
error if the user attempts to apply to a signal.
|
|
|
|
_Graphical Demo Programs_
|
|
|
|
To run the following animation/GUI demos, simply set the language
|
|
level to FrTime, open the corresponding file, and Execute. See the
|
|
demo source code for more information.
|
|
|
|
orbit-mouse.ss : A collection of balls that move in circles around
|
|
the mouse pointer.
|
|
|
|
piston.ss : Simulation of a piston/cylinder.
|
|
|
|
rotation.ss : Balls moving in circles.
|
|
|
|
delay-mouse.ss : A trail of balls following the mouse.
|
|
|
|
ball-on-string.ss : A ball chasing the mouse.
|
|
|
|
pong.ss : A simple pong/air-hockey game. The left paddle moves with
|
|
numeric keypad; the right paddle moves with the mouse. The 'r' key
|
|
resets the score.
|
|
|
|
net-pong-*.ss : A networked version of the pong/air-hockey game.
|
|
Currently known to work under Linux. To play, open the client on one
|
|
machine and the server on another. Execute both (and require if
|
|
necessary, depending on language level). Evaluate (self) on each.
|
|
Results will be something like:
|
|
|
|
[client]
|
|
> (self)
|
|
#3(tid 128.148.38.2:1180 main)
|
|
|
|
and
|
|
[server]
|
|
> (self)
|
|
#3(tid 128.148.33.71:1178 main)
|
|
|
|
Now tell each machine about the other:
|
|
[client]
|
|
> (set-cell! server (make-tid '128.148.33.71 1178 'frtime-heart))
|
|
|
|
[server]
|
|
> (set-cell! client (make-tid '128.148.38.2 1180 'frtime-heart))
|
|
|
|
Note the differences between the #3(tid ...) output and the (make-tid ...)
|
|
commands---there is no colon (:) between the host and port, and main becomes
|
|
'frtime-heart.
|
|
|
|
After setting the cells, complete the connection by clicking the left
|
|
mouse button in both animation windows. The player running the server
|
|
can reset the score by pressing 'r'.
|
|
|
|
pizza.ss : A simple "pizza ordering" user interface based on an HtDP
|
|
exercise.
|
|
|
|
calculator.ss : A simple calculator interface, also based on an HtDP
|
|
exercise except that the result updates continuously as the arguments
|
|
and operator change.
|
|
|
|
Robb Cutler's Examples
|
|
|
|
analog-clock.ss : An animated real-time clock. A slider adjusts the radius
|
|
of the face. Click and drag to move the face around.
|
|
|
|
growing-points.ss : A field of points that grow as the mouse approaches.
|
|
|
|
needles.ss : A field of needles that point at the mouse.
|
|
|
|
_FtA (Forte GUI library)_
|
|
|
|
MACROS
|
|
------
|
|
|
|
To get the macros:
|
|
(require (lib "mixin-macros.ss" "frtime" "demos" "gui"))
|
|
|
|
> (behavior->callbacks field-name update-call)
|
|
Generates a mixin for allowing a behavior to control a widget.
|
|
The mixin has two arguments. The mixin's first argument is the
|
|
default value for field-name, and the seconds argument is the
|
|
class being mixed.
|
|
|
|
> (events->callbacks field-name update-call)
|
|
Generates a mixin for allowing an event stream to drive
|
|
callbacks. The one argument to the resulting mixin is the
|
|
class to be extended
|
|
|
|
> (callbacks->args-evts stream-name callback (args-to-callback ...))
|
|
Generates a mixin that sends an event on stream-name when
|
|
callback is called. The class has an init field called
|
|
[stream-name]-event-processor, which is a function. The
|
|
function is applied to an event stream that has an
|
|
occurence every time callback is called, and the value
|
|
of the events is a list of the arguments to the callback.
|
|
The public method (get-[stream-name]) is a public method
|
|
of the resulting class that gets the result of applying
|
|
[stream-name]-event-processor to the stream of args-evts.
|
|
|
|
FtA provides event-is-val, split-mouse-events/type, and
|
|
split-key-events/type for use as initialization arguments.
|
|
event-is-val can be used for [stream-name]-event-processor
|
|
when the event should just be the value of the first
|
|
argument of the callback. split-*-events/type sets up an
|
|
appropriate split (see FrTime docs for split information,
|
|
MrEd docs for key-event codes and mouse-event types).
|
|
|
|
|
|
MIXINS
|
|
------
|
|
|
|
Some common mixins have already been defined and applied.
|
|
To get these:
|
|
(require "fred.ss" "frtime" "demos" "gui")
|
|
|
|
> (add-mouse-access super-class)
|
|
Derived from callbacks->args-evts.
|
|
stream-name: mouse-events
|
|
|
|
> (add-focus-access super-class)
|
|
Derived from callbacks->args-evts
|
|
stream-name: focus-events
|
|
|
|
> (add-keypress-split super-class)
|
|
Derived from callbacks->args-evts.
|
|
stream-name: key-events
|
|
|
|
> (add-callback-access value-extractor default-value super-class)
|
|
value-extractor is a method of two arguments (a widget
|
|
and a control event) that gets a value for the widget.
|
|
default-value is the default value for the widget. Adds
|
|
(get-value-e) and (get-value-b) to super-class, where
|
|
get-value-e returns an event stream representing the
|
|
value of the widget, and get-value-b returns a behavior
|
|
representing the value of the widget.
|
|
|
|
> (add-callback-access/loop value-extractor default-value super-class)
|
|
does the work of add-callback-access, but also adds
|
|
an initialization argument value-set, which is an
|
|
event stream that sets the value of the widget at
|
|
each event.
|
|
|
|
> (add-focus-on-event super-class)
|
|
Derived from events->callbacks.
|
|
field-name: focus-when
|
|
|
|
|
|
UTILITY
|
|
-------
|
|
|
|
> (standard-lift widget value-method value-default)
|
|
standard-lift applys a common set of mixins to the
|
|
widget. It applies add-mouse-access, add-focus-access,
|
|
and it applys the result of behavior->callback for
|
|
label and enable. It also applies add-callback-access
|
|
with value-method as the value-extractor, and
|
|
value-default as the default-value.
|
|
Widgets that have been standard-lift'ed:
|
|
ft-button%
|
|
ft-radio-box%
|
|
ft-choice%
|
|
ft-list-box%
|
|
|
|
|
|
> (standard-lift/loop widget value-method value-default)
|
|
standard-lift/loop is the same as standard-lift,
|
|
except thatit applies add-callback-access/loop
|
|
instead of add-callback-access.
|
|
Widgets that have been standard-lift/loop'ed:
|
|
ft-check-box%
|
|
ft-slider%
|
|
ft-text-field%
|
|
|
|
|
|
simple.ss
|
|
---------
|
|
|
|
Many useful utilities have been put in
|
|
(require "simple.ss" "frtime" "demos" "gui")
|
|
feel free to look around and use the ones you think are
|
|
useful.
|
|
|