21 Back-channels
Up until this point, computations communicate by consuming arguments and producing values. Mutation enables more channels of communication between computations via shared mutable data.
As an example, recall our counter world program from Simple world:
;; A Counter is a (counter-world% Natural) (define-class counter-world% (fields n) ... ;; on-tick : -> Counter (define (on-tick) (new counter-world% (add1 (this . n))))) (big-bang (new counter-world% 0))
To illustrate how mutable data provides alternative channels of communication, let’s develop a variant of the program that communicates the state of the world through an implicit stateful back-channel.
;; A Counter is a (counter-world% Natural) (define-class counter-world% (fields n) ... ;; on-tick : -> Counter (define (on-tick) (begin (set-field! n (add1 (send this n))) this))) (big-bang (new counter-world% 0))
Notice how the new on-tick method doesn’t produce a new counter-world% object with an incremented counter; instead it mutates its own counter and returns its (mutilated) self.
You’ll find that this program appears to behave just like the old version, but backchannels open up new forms of interaction (and interference) that may not be intended. For example, can you predict what thise program will do?
(launch-many-worlds (big-bang (new counter-world% 0)) (big-bang (new counter-world% 0)))
How about this (seemingly equivalent) one?
(define w (new counter-world% 0)) (launch-many-worlds (big-bang w) (big-bang w))