guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Potluck dish - Simple functional reactive programming


From: David Thompson
Subject: Re: Potluck dish - Simple functional reactive programming
Date: Mon, 17 Feb 2014 20:17:18 -0500
User-agent: Notmuch/0.17 (http://notmuchmail.org) Emacs/24.3.1 (x86_64-pc-linux-gnu)

David Thompson <address@hidden> writes:
> 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.

I spent the day improving my potluck dish.  The public API remains the
same, but the implementation is quite a bit different.  The previous
implementation suffered from 2 major flaws:

1) The GC would never collect orphaned signals because of the doubly
linked structure of the graph

2) Redefining a signal 'foo' at the REPL doesn't splice the new value of
'foo' into the graph where the old value of 'foo' was.  Thus, working
with signals at the REPL was painful.

So, this new implementation uses an additional data type called
<signal-box> to deal with the dynamic nature of REPL-driven development.
The user is always working with signal boxes, not the signals
themselves.  By using the 'define-signal' macro, redefining the signal
'foo' at the REPL will replace the contents of the box with the new
signal.  If any other signals depended on 'foo', they automagically
begin to work with the signal within the box 'foo'.

To deal with doubly linked nodes, a weak key hash table is used to store
signal outputs.  This allows input signals to push values to output
signals without protecting them from the clutches of the garbage
collector.  When an output signal is no longer referenced, the input
signal will stop pushing new values to it.

Here's the updated version of the example from last time.  Note that
using 'after-gc-hook' is actually a bad idea, but I did it anyway. ;)

(define-signal gc-counter (make-signal 0))
(define-signal gc-label
  (signal-map (lambda (counter)
                (let ((text (format #f "GCs: ~d" counter)))
                  (make-label font text (vector2 0 40))))
              gc-counter))

(add-hook! after-gc-hook
           (lambda ()
             (schedule game-agenda
                       (lambda ()
                         (signal-set! gc-counter
                                      (1+ (signal-ref gc-counter)))))))

This module is currently part of the wip-frp branch of the guile-2d repo
on gitorious.

https://gitorious.org/guile-2d/guile-2d/source/3a786ddee63d4505cdb142442e880950698223f0:2d/signal.scm

Thanks for following along,
- David Thompson

Attachment: signal.scm
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]