FrTime: A Language for Reactive Programs
The frtime.ss language supports declarative construction of reactive systems in a syntax very similar to that of MzScheme. To interact with FrTime, select FrTime from the "Choose Language" menu. You can also make FrTime the language for a module:
(module <module-name> frtime |
<module-body>) |
1 Primitives
stands for an undefined value.
(undefined? val) → boolean? |
val : any/c |
return #t iff val is undefined.
val : any/c |
returns #t iff val is a behavior (a time-varying value whose current value can be projected at any time).
val : any/c |
returns #t iff val is an event (a time-varying stream of values that can occur at arbitrary times).
val : any/c |
returns #t iff val is a signal. (signal? v) is equivalent to (or (behavior? v) (event? v)).
updates approximately once per second with the value of (current-seconds).
updates frequently with the value of (current-inexact-milliseconds).
is an event that never occurs.
2 Defining Custom Input Signals
returns a signal whose values initially track that of init-expr, but that may be rewired to a different signal by set-cell!.
cell : signal? |
val : signal? |
rewires cell (which must have been created by new-cell) to take on the value(s) of val.
(event-receiver) → event? |
returns an event stream that can be triggered imperatively by send-event.
(send-event rcvr val) → void? |
rcvr : event? |
val : any/c |
emits val on rcvr (which must have been created by event-receiver).
3 Signal-Processing Procedures
val : any/c |
projects the current value of a behavior or constant.
val : behavior? |
duration : number? |
delays val by duration milliseconds.
computes a numeric approximation of the integral of val with respect to time (measured in milliseconds).
(derivative val) → behavior? |
val : behavior? |
computes a numeric approximation of the derivative of val with respect to time.
| |||
|
returns an event stream that fires whenever ev fires, whose values are transformed by application of proc.
| |||
|
returns an event stream that passes through only the values from ev for which pred returns #t.
ev : event? |
merges all of the input event sources into a single event source.
ev : event? |
returns an event source that carries only the first occurrence of ev. (The rest are filtered out.)
val : behavior? |
returns an event source that occurs each time the argument behavior changes. The value of the occurrence is the behavior’s new value.
ev : event? |
constructs a behavior that starts out as init and then takes on the last value produced by ev
ev : event? |
returns a behavior that starts as init. Each time ev yields a (potentially time-varying) value, the behavior switches to that value.
ev : event? |
init : any/c |
constructs an event source by accumulating changes (carried by the given event source) over an initial value.
ev : event? |
init : any/c |
combines functionality from accum-e and hold to construct a behavior. (accum-b ev init) is equivalent to (hold init (accum-e ev init)).
ev : event? | ||||||||
init : any/c | ||||||||
|
is similar to accum-e, except the transformer function is fixed and is applied to the event occurrence and the current accumulator (in that order).
ev : event? |
init : any/c |
is similar to collect-e in the same way as accum-b is similar to accum-e.
val : behavior? |
returns an event stream that carries an occurrence each time val changes from #f to anything else.
(lift-strict proc val ) → any |
val : any/c |
provides a mechanism for applying ordinary Scheme primitives to behaviors. If any of the vals are behaviors, returns a behavior whose current value is always equal to (proc (value-now arg) ...). In FrTime, many MzScheme primitives are implicitly lifted.
The following forms allow importation of lifted procedures that aren’t included in the basic FrTime language.
4 Fred: Functional Reactive Wrapper around MrEd
superclass: frame% | ||
|
[label label]
[
[parent parent]
[width width]
[height height]
[x x]
[y y]
[style style]
[enabled enabled]
[border border]
[spacing spacing]
[alignment alignment]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]
[shown shown]])
width : (or/c (integer-in 0 10000) false/c) = #f
height : (or/c (integer-in 0 10000) false/c) = #f
x : (or/c (integer-in -10000 10000) false/c) = #f
y : (or/c (integer-in -10000 10000) false/c) = #f
style
:
'no-system-menu 'hide-menu-bar
'mdi-parent 'mdi-child
'toolbar-button 'float 'metal))
=
enabled : any/c = #t
border : (integer-in 0 1000) = 0
spacing : (integer-in 0 1000) = 0
alignment
:
(one-of/c 'top 'center 'bottom))
=
'(center top)
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #t
stretchable-height : any/c = #t
shown : any/c = #f
The constructor arguments are as in frame%, except that shown label, enabled, stretchable-width, and stretchable-height may be time-varying.
superclass: message% | ||
|
[label label]
[parent parent]
[
[style style]
[font font]
[enabled enabled]
[vert-margin vert-margin]
[horiz-margin horiz-margin]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]])
→ (is-a?/c ft-message%)
label
:
(or-of/c 'app 'caution 'stop))
parent
:
font : (is-a?/c font%) = (scheme normal-control-font)
vert-margin : (integer-in 0 1000) = 2
horiz-margin : (integer-in 0 1000) = 2
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #f
stretchable-height : any/c = #f
The constructor arguments are the same as in message%, except that label, enabled, stretchable-width, and stretchable-height may be time-varying.
superclass: button% | ||
|
[label label]
[parent parent]
[
[style style]
[font font]
[enabled enabled]
[vert-margin vert-margin]
[horiz-margin horiz-margin]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]])
→ (is-a?/c ft-button%)
parent
:
font : (is-a?/c font%) = (scheme normal-control-font)
enabled : any/c = #t
vert-margin : (integer-in 0 1000) = 2
horiz-margin : (integer-in 0 1000) = 2
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #f
stretchable-height : any/c = #f
The constructor arguments are the same as in message%, except that label, enabled, stretchable-width, and stretchable-height may be time-varying.
(send a-ft-button get-value-e) → event?
returns an event stream that yields a value whenever the user clicks the button.
superclass: check-box% | ||
|
[label label]
[parent parent]
[
[style style]
[value value]
[font font]
[enabled enabled]
[vert-margin vert-margin]
[horiz-margin horiz-margin]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]
[value-set value-set]])
→ (is-a?/c ft-check-box%)
parent
:
value : any/c = #f
font : (is-a?/c font%) = (scheme normal-control-font)
enabled : any/c = #t
vert-margin : (integer-in 0 1000) = 2
horiz-margin : (integer-in 0 1000) = 2
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #f
stretchable-height : any/c = #f
The constructor arguments are the same as in check-box%, except that label, enabled, stretchable-width, and stretchable-height may be time-varying. Also, any occurrence on value-set sets the check box’s state to that of the event value.
(send a-ft-check-box get-value-b) → behavior?
returns a value that always reflects the current state of the check box.
superclass: slider% | ||
|
[label label]
[min-value min-value]
[max-value max-value]
[parent parent]
[
[init-value init-value]
[style style]
[font font]
[enabled enabled]
[vert-margin vert-margin]
[horiz-margin horiz-margin]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]
[value-set value-set]])
→ (is-a?/c ft-slider%)
min-value : (integer-in -10000 10000)
max-value : (integer-in -10000 10000)
parent
:
init-value : (integer-in -10000 10000) = min-value
style
:
'vertical-label 'horizontal-label
'deleted))
=
'(horizontal)
font : (is-a?/c font%) = normal-control-font
enabled : any/c = #t
vert-margin : (integer-in 0 1000) = 2
horiz-margin : (integer-in 0 1000) = 2
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
The constructor arguments are the same as in check-box%, except that label, enabled, stretchable-width, and stretchable-height may be time-varying. Also, any occurrence on value-set sets the slider’s state to that of the event value.
(send a-ft-slider get-value-b) → behavior?
returns a value that always reflects the current state of the slider.
superclass: text-field% | ||
|
[label label]
[parent parent]
[
[init-value init-value]
[style style]
[font font]
[enabled enabled]
[vert-margin vert-margin]
[horiz-margin horiz-margin]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]
[value-set value-set]])
parent
:
init-value : string? = ""
style
:
'vertical-label 'horizontal-label
'deleted))
=
'(single)
font : (is-a?/c font%) = (scheme normal-control-font)
enabled : any/c = #t
vert-margin : (integer-in 0 1000) = 2
horiz-margin : (integer-in 0 1000) = 2
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #t
The constructor arguments are the same as in check-box%, except that label, enabled, stretchable-width, and stretchable-height may be time-varying. Also, any occurrence on value-set sets the text field’s state to that of the event value.
(send a-ft-text-field get-value-b) → behavior?
returns a value that always reflects the current state of the text field.
superclass: radio-box% | ||
|
[label label]
[choices choices]
[parent parent]
[
[style style]
[selection selection]
[font font]
[enabled enabled]
[vert-margin vert-margin]
[horiz-margin horiz-margin]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]
[value-set value-set]])
→ (is-a?/c ft-radio-box%)
choices : (or/c (listof label-string?) (listof (is-a?/c bitmap%)))
parent
:
style
:
'vertical-label 'horizontal-label
'deleted))
=
'(vertical)
selection : nonnegative-exact-integer? = 0
font : (is-a?/c font%) = normal-control-font
enabled : any/c = #t
vert-margin : (integer-in 0 1000) = 2
horiz-margin : (integer-in 0 1000) = 2
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #f
stretchable-height : any/c = #f
The constructor arguments are the same as in check-box%, except that label, enabled, stretchable-width, and stretchable-height may be time-varying. Also, any occurrence on value-set sets the text field’s state to that of the event value.
(send a-ft-radio-box get-selection-b) → behavior?
returns a value that always reflects the currently selected element in the radio box.
superclass: choice% | ||
|
[label label]
[choices choices]
[parent parent]
[
[style style]
[selection selection]
[font font]
[enabled enabled]
[vert-margin vert-margin]
[horiz-margin horiz-margin]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]
[value-set value-set]])
→ (is-a?/c ft-choice%)
choices : (listof label-string?)
parent
:
style
:
'deleted))
=
selection : nonnegative-exact-integer? = 0
font : (is-a?/c font%) = (scheme normal-control-font)
enabled : any/c = #t
vert-margin : (integer-in 0 1000) = 2
horiz-margin : (integer-in 0 1000) = 2
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #f
stretchable-height : any/c = #f
The constructor arguments are the same as in check-box%, except that label, enabled, stretchable-width, and stretchable-height may be time-varying. Also, any occurrence on value-set sets the text field’s state to that of the event value.
(send a-ft-choice get-selection-b) → behavior?
returns a value that always reflects the currently selected element in the choice control.
superclass: list-box% | ||
|
[label label]
[choices choices]
[parent parent]
[
[style style]
[selection selection]
[font font]
[label-font label-font]
[enabled enabled]
[vert-margin vert-margin]
[horiz-margin horiz-margin]
[min-width min-width]
[min-height min-height]
[stretchable-width stretchable-width]
[stretchable-height stretchable-height]
[value-set value-set]])
→ (is-a?/c ft-list-box%)
choices : (listof label-string?)
parent
:
style
:
'vertical-label 'horizontal-label
'deleted))
=
'(single)
font : (is-a?/c font%) = (scheme view-control-font)
label-font : (is-a?/c font%) = (scheme normal-control-font)
enabled : any/c = #t
vert-margin : (integer-in 0 1000) = 2
horiz-margin : (integer-in 0 1000) = 2
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #t
stretchable-height : any/c = #t
The constructor arguments are the same as in check-box%, except that label, enabled, stretchable-width, and stretchable-height may be time-varying. Also, any occurrence on value-set sets the text field’s state to that of the event value.
(send a-ft-list-box get-selection-b) → behavior?
returns a value that always reflects the primary selection in the list box.
(send a-ft-list-box get-selections-b) → behavior?
returns a value that always reflects the current set of selected elements in the list box.
5 Graphical Demo Programs
TODO: document the animation library itself!
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.
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.
The next three animation examples are courtesy of Robb Cutler:
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.