Hello Guilers, I didn't have time to put together a proper potluck dish, but I wanted to find something to share anyway.
Lately I've been playing around with functional reactive programming (FRP) applied to video games. This style of programming allows for a declarative, functional way of describing time-varying values. Contrast this method of programming with more traditional hooks and callbacks. My FRP module can be used on top of hooks to escape callback hell. And now for a simple example. This morning I was writing a program using my game engine, guile-2d, and I wanted to display the number of times the GC has been run in the game window. Without FRP I could have done something like: (define gc-label-position (vector2 0 40)) (define gc-counter 0) (define (make-gc-label) (let ((text (format #f "GCs: ~d" counter))) (make-label font text gc-label-position))) (define gc-label (make-gc-label)) (add-hook! after-gc-hook (lambda () (set! gc-counter (1+ gc-counter)) (set! gc-label (make-gc-label)))) This code isn't terrible, but wouldn't it be nice to declare that 'gc-label' will always contain a string with the number of GC runs in it instead? Enter FRP: (define gc-label-position (vector2 0 40)) (define gc-counter (make-root-signal 0)) (define gc-label (signal-map (lambda (counter) (let ((text (format #f "GCs: ~d" counter))) (make-label font text gc-label-position))) gc-counter)) (add-hook! after-gc-hook (lambda () (signal-set! gc-counter (1+ (signal-ref gc-counter))))) 'gc-counter' and 'gc-label' both become 'signals', or time-varying values. Now, when the GC runs, the 'gc-counter' signal is incremented by 1. The act of setting 'gc-counter' triggers propagation of the counter to the 'gc-label' signal which maps the counter to a new label that prints the current number of GC runs. Magic! Note that 'after-gc-hook' is still needed to bootstrap the signal graph, but once that is out of the way it's signals all the way down. This example was fairly trivial, but what if the desired chain reaction was more complicated? Writing the logic using regular callback procedures would become a nightmare. The nightmare that JavaScript programmers constantly find themselves in. And that's my potluck dish! I'm currently working on a new version of this API that will allow the signal graph to handle the dynamic environment of the REPL, but it's not ready yet. Thanks to all of the Guile maintainers and contributors for the great work these past 3 years! - David Thompson
signals.scm
Description: Binary data