lux:   brilliant interactive programs
1 Structure of a lux Program
call-with-chaos
fiat-lux
2 The Word
word?
gen:  word
word-fps
word-label
word-evt
word-event
word-tick
word-output
word-return
2.1 Word Construction
word
2.2 Helpers
lux-standard-label
3 Chaos
3.1 Racket GUI Chaos
make-gui
3.1.1 Drawing Values
make-gui/  val
3.1.2 Tracking Keyboard State
key-state
make-key-state
key-event?
key-event-code
key-state-update!
key-state-set?
key-state-set?!
3.1.3 Tracking Mouse State
mouse-state
make-mouse-state
mouse-event?
mouse-event-xy
mouse-state-update!
3.2 Pair Chaos
make-pair
3.3 Implementing a Chaos
chaos?
gen:  chaos
chaos-start!
chaos-yield
chaos-event
chaos-output!
chaos-label!
chaos-swap!
chaos-stop!
7.1

lux: brilliant interactive programs

Jay McCarthy

 (require lux) package: lux

The lux module provides an efficient way to build interactive programs that consist of plain mathematical functions. It is comparable to 2htdp/universe, although designed to allow more parameterization of how the program interacts.

Check out some examples in the examples directory in the source.

    1 Structure of a lux Program

    2 The Word

      2.1 Word Construction

      2.2 Helpers

    3 Chaos

      3.1 Racket GUI Chaos

        3.1.1 Drawing Values

        3.1.2 Tracking Keyboard State

        3.1.3 Tracking Mouse State

      3.2 Pair Chaos

      3.3 Implementing a Chaos

1 Structure of a lux Program

A lux program chooses how it will interact be selecting a chaos and calling call-with-chaos with that chaos and a thunk that calls fiat-lux with a word. fiat-lux may be called any number of nested times within a call to call-with-chaos. Each subsequent fiat-lux takes over the chaos until the word completes. It is not typically possible to use words with arbitrary chaoses, as the chaos specifies how the word interacts through events and output values.

When designing words, it is important to realize that word updating functions like word-tick do not have to return a word of the same kind.

procedure

(call-with-chaos c t)  any

  c : chaos?
  t : (-> any)
Runs t with c as the current chaos.

procedure

(fiat-lux w)  any

  w : word?
Runs w with the current chaos.

2 The Word

A word is a generic interface the encapsulates the interactive behavior of a lux program.

procedure

(word? x)  boolean?

  x : any/c
Identifies words.

value

gen:word : any/c

The generic interface binding for words.

The word methods are as follows:

procedure

(word-fps w)  flonum?

  w : word?
Returns the desired rate of updating for w as frames-per-second. By default, 60.0 is returned.

procedure

(word-label w frame-time)  string?

  w : word?
  frame-time : flonum?
Returns a label for w that could use frame-time to show the performance of the word rendering. By default, returns (lux-standard-label "Lux" frame-time).

procedure

(word-evt w)  evt?

  w : word?
Returns a synchronizable event that the word w requires notification of. By default, returns never-evt.

procedure

(word-event w e)  word?

  w : word?
  e : any/c
Returns a word based on w that integrates the information from the event e. The type of e is dependent on the current chaos. If this returns #f, then the lux programs stops. By default, returns w.

procedure

(word-tick w)  word?

  w : word?
Returns a word based on w after one tick of abstract time. This will be called (word-fps w) times per second. If this returns #f, then the lux programs stops. By default, returns w.

procedure

(word-output w)  any/c

  w : word?
Returns the output value of w. The type that this returns is dependent on the current chaos. By default, returns #f. chaoses should always allow #f and use it to mean "no output".

procedure

(word-return w)  any/c

  w : word?
Returns a value for w when the lux programs stops, which happens if word-event or word-tick return #f. By default, returns w.

2.1 Word Construction

A word can be created by defining a new struct that implements the gen:word generic interface; or, it can be defined using word. The first method is best when it is easy to capture the state of the creation in a structure and the second is preferable when it is better to capture the state implicitly in the captured closures. In the author’s experience, the second is also best for creations with complex control flow, because different sorts of words can be returned in different circumstances.

procedure

(word [base    
  fps    
  label    
  evt    
  event    
  tick    
  output    
  return])  word?
  base : (or/c #f word?) = #f
  fps : real? = ....
  label : (or/c string? (-> real? string?)) = ....
  evt : evt? = ....
  event : (-> any/c (or/c #f word?)) = ....
  tick : (-> (or/c #f word?)) = ....
  output : any/c = ....
  return : any/c = ....
Return a word where the implementations of the methods are as given or inherited from base or the defaults (described above). The only subtleties are that: (1) label may be a string which is used directly and the frame time is not available; (2) event is a function that only receives the generated event; (3) tick is a thunk. The assumption is that the caller of word can arrange for the value returned to be captured by these closures if necessary.

2.2 Helpers

procedure

(lux-standard-label s frame-time)  string?

  s : string?
  frame-time : flonum?
Returns (string-append s ": " fts) where fts formats frame-time as milliseconds and as frames per second.

3 Chaos

A chaos is generic interface for an empty manifestation of an interactive space that is given form by the word and fiat-lux.

3.1 Racket GUI Chaos

 (require lux/chaos/gui) package: lux

This module provides the standard chaos that most users of lux will use.

procedure

(make-gui [#:mode mode    
  #:opengl-hires? opengl-hires?    
  #:start-fullscreen? start-fullscreen?    
  #:frame-style frame-style    
  #:icon icon    
  #:x x    
  #:y y    
  #:width width    
  #:height height    
  #:monitor monitor])  chaos?
  mode : 
(or/c (one-of/c 'draw 'gl-compat 'gl-core)
      (is-a?/c gl-config%))
 = 'draw
  opengl-hires? : boolean? = #f
  start-fullscreen? : boolean? = #f
  frame-style : (listof symbol?) = '()
  icon : (or/c #f path-string? (is-a?/c bitmap%)) = #f
  x : (or/c exact-nonnegative-integer? (one-of/c 'left 'center 'right))
   = 'center
  y : (or/c exact-nonnegative-integer? (one-of/c 'top 'center 'bottom))
   = 'center
  width : exact-nonnegative-integer? = 800
  height : exact-nonnegative-integer? = 600
  monitor : (or/c false/c exact-nonnegative-integer?) = #f
Returns a chaos that opens a GUI frame with a canvas to draw on. The frame is placed at position x,y on monitor monitor; if monitor is #f, the monitor containing the mouse pointer is used. The default size of the frame is widthxheight. The icon for the application is set to icon. If start-fullscreen? is true, then the frame is initially fullscreen. The frame’s style is set to frame-style.

The canvas is set up for drawing based on mode. If mode is 'draw, then the canvas assumes that racket/draw is used. If other values are used, then the canvas is drawn with OpenGL. If mode is 'gl-compat, then a compatibility OpenGL profile is used. If mode is 'gl-core, then a core OpenGL profile is used. If mode is a gl-config% object, then it is used to initialize the canvas. If opengl-hires? is #t, then the resulting gl-config% object will have high resolution mode set.

The values that word-event is called with are either 'close (for when the window’s close button is pressed), a key-event% object for when keys are pressed, or a mouse-event% object for when the mouse is used.

The values that word-output should return are functions that satisfy the contract (-> real? real? (is-a?/c dc<%>) any) where the first argument is the width of the canvas, the second is the height, and the third is the canvas’s drawing context.

3.1.1 Drawing Values

 (require lux/chaos/gui/val) package: lux

This module provides a helpful function for drawing functional images with lux/chaos/gui.

procedure

(make-gui/val [#:scale? scale?])

  
(-> pict-convertible?
    (-> real? real? (is-a?/c dc<%>) any))
  scale? : boolean? = #t
Produces a function that draws pict-convertible? values on to lux/chaos/gui’s drawing context. If scale? is true, then the value will be scaled to file the drawing context (while preserving aspect ratio), otherwise the value will be drawn in the center as-is.

3.1.2 Tracking Keyboard State

 (require lux/chaos/gui/key) package: lux

This module provides a set of functions for tracking keyboard state for use inside of word-tick, rather than updating word state with each event as in word-event. Such as system may be appropriate for interactive programs where input is only has an impact at a consistent tick rate.

struct

(struct key-state (keys
    shift?
    control?
    meta?
    alt?
    mod3?
    mod4?
    mod5?))
  keys : hash?
  shift? : boolean?
  control? : boolean?
  meta? : boolean?
  alt? : boolean?
  mod3? : boolean?
  mod4? : boolean?
  mod5? : boolean?
Stores a mapping of which keys are presently pressed.

procedure

(make-key-state)  key-state?

Produces a key-state? object with appropriate defaults.

procedure

(key-event? x)  boolean?

  x : any/c
Identifies key events.

procedure

(key-event-code ke)

  (or/c (cons/c 'release (or/c char? key-code-symbol?)) (or/c char? key-code-symbol?))
  ke : key-event?
Returns the code of the key event.

procedure

(key-state-update! ks ke)  any

  ks : key-state?
  ke : key-event?
Updates ks with ke.

procedure

(key-state-set? ks kc)  boolean?

  ks : key-state?
  kc : (or/c char? key-code-symbol?)
Returns true if kc is pressed in kc.

procedure

(key-state-set?! ks kc)  boolean?

  ks : key-state?
  kc : (or/c char? key-code-symbol?)
Returns true if kc is pressed in kc and sets its pressed status to false..

3.1.3 Tracking Mouse State

 (require lux/chaos/gui/mouse) package: lux

This module provides a set of functions for tracking mouse state for use inside of word-tick, rather than updating word state with each event as in word-event. Such as system may be appropriate for interactive programs where input is only has an impact at a consistent tick rate.

struct

(struct mouse-state (x
    y
    left?
    right?
    middle?
    shift?
    control?
    meta?
    alt?
    mod3?
    mod4?
    mod5?))
  x : real?
  y : real?
  left? : boolean?
  right? : boolean?
  middle? : boolean?
  shift? : boolean?
  control? : boolean?
  meta? : boolean?
  alt? : boolean?
  mod3? : boolean?
  mod4? : boolean?
  mod5? : boolean?
Stores the active state of the mouse.

Produces a mouse-state? object with appropriate defaults.

procedure

(mouse-event? x)  boolean?

  x : any/c
Identifies mouse events.

procedure

(mouse-event-xy me)  
real? real?
  me : mouse-event?
Returns the position of the mouse event.

procedure

(mouse-state-update! ms me)  any

  ms : mouse-state?
  me : mouse-event?
Updates ms with me.

3.2 Pair Chaos

 (require lux/chaos/pair) package: lux

This module provides a chaos that pairs two other chaos objects for lux programs with multiple interfaces.

procedure

(make-pair left right)  chaos?

  left : chaos?
  right : chaos?
Returns a chaos where the input event type is the union of the input events of left and right and the output type is a pair of the output types of left and right.

3.3 Implementing a Chaos

 (require lux/chaos) package: lux

Users of lux will probably not need to implement chaoses, but will use those that are standard.

procedure

(chaos? x)  boolean?

  x : any/c
Identifies chaoss.

value

gen:chaos : any/c

The generic interface binding for chaoses.

The chaos methods are as follows:

procedure

(chaos-start! c)  any

  c : chaos?
Called at the start of using c as the current chaos. By default, does nothing.

procedure

(chaos-yield c e)  any

  c : chaos?
  e : evt?
Synchronizes on e in a way safe for c. By default, calls sync.

procedure

(chaos-event c)  evt?

  c : chaos?
Returns an event that when ready returns a c event value. By default, returns never-evt.

procedure

(chaos-output! c o)  any

  c : chaos?
  o : any/c
Outputs o to c. chaoses should always allow #f and use it to mean "no output". By default, does nothing.

procedure

(chaos-label! c s)  any

  c : chaos?
  s : string?
Outputs s as the label of c. By default, does nothing.

procedure

(chaos-swap! c t)  any

  c : chaos?
  t : (-> any)
Calls t while preparing c to run a different word. By default, just calls t.

procedure

(chaos-stop! c)  any

  c : chaos?
Called at the end of using c as the current chaos. By default, does nothing.