summaryrefslogtreecommitdiff
path: root/posts/guile-2d-frp.md
diff options
context:
space:
mode:
Diffstat (limited to 'posts/guile-2d-frp.md')
-rw-r--r--posts/guile-2d-frp.md64
1 files changed, 64 insertions, 0 deletions
diff --git a/posts/guile-2d-frp.md b/posts/guile-2d-frp.md
new file mode 100644
index 0000000..7dedbbb
--- /dev/null
+++ b/posts/guile-2d-frp.md
@@ -0,0 +1,64 @@
+title: Functional Reactive Programming in Scheme with guile-2d
+date: 2014-03-09 21:00:00
+tags: foss, gnu, guile, scheme, gamedev, wsu
+summary: Introduction to FRP in Scheme with guile-2d
+---
+
+Last month, the [GNU Guile](https://gnu.org/s/guile) project
+celebrated the 3rd anniversary of its 2.0 release with a hacker
+[potluck](http://savannah.gnu.org/forum/forum.php?forum_id=7887).
+Guilers were encouraged to bring a tasty hack to the mailing list to
+share with everyone. My dish was a simple
+[functional reactive programming](https://en.wikipedia.org/wiki/Functional_reactive_programming)
+library.
+
+Functional reactive programming (FRP) provides a way to describe
+time-varying values and their relationships using a functional and
+declarative programming style. To understand what this means, let’s
+investigate a typical variable definition in Scheme. The expression
+`(define c (+ a b))` defines the variable `c` to be the sum of
+variables `a` and `b` at the time of evaluation. If `a` or `b` is
+assigned a new value, `c` remains the same. However, for applications
+that deal with state that transforms over time, it would be convenient
+if we could define `c` to react to changes in `a` and `b` by
+recomputing the sum. Contrast this approach with the more traditional
+style of modeling dynamic state via events and callbacks. A lot of
+programmers, myself included, have written code with so many callbacks
+that the resulting program is unmaintainable spaghetti code. Callback
+hell is real, but if you accept FRP into your heart then you will be
+saved!
+
+By now you’re probably wondering: “What the hell does all this mean?”
+So, here’s a real-world example of guile-2d’s FRP API:
+
+```scheme
+(define-signal position
+ (signal-fold v+ (vector2 320 240)
+ (signal-map (lambda (v)
+ (vscale v 4))
+ (signal-sample game-agenda 1 key-arrows))))
+```
+
+In guile-2d, time-varying values are called “signals”. The above
+signal describes a relationship between the arrow keys on the keyboard
+and the position of the player. `signal-sample` is used to trigger a
+signal update upon every game tick that provides the current state of
+the arrow keys. `key-arrows` is a vector2 that maps to the current
+state of the arrow keys, allowing for 8 direction movement. This
+vector2 is then scaled 4x to make the player move faster. Finally,
+the scaled vector is added to the previous player position via
+`signal-fold`. The player’s position is at `(320, 240)` initially.
+As you can see, there are no callbacks and explicit mutation needed.
+Those details have been abstracted away, freeing the programmer to
+focus on more important things.
+
+I think it’s helpful to see FRP in action to really appreciate the
+magic. So, check out this screencast!
+
+ <video src="/videos/guile-2d-frp-demo.webm"
+ style="width:640px;height:360px;" controls>
+ </video>
+
+To see all of the juicy implementation details, check out the
+[git repository](https://gitorious.org/sly/sly/source/sly/signal.scm).
+Thanks for following along!