syndicate-2017/racket/syndicate/examples/actor/f-to-c5.rkt

39 lines
1.4 KiB
Racket

#lang syndicate
;; After the Fahrenheit-to-Celsius converter example in "Fabrik - A
;; Visual Programming Environment", Ingalls, Wallace, Chow, Ludolph
;; and Doyle, OOPSLA 1988.
;;---------------------------------------------------------------------------
(define (make-idempotent-field name initial-value [=? equal?])
(local-require (submod syndicate/actor implementation-details))
(define f (make-field name initial-value))
(match-lambda*
[(list) (f)]
[(list new-value)
(unless (=? (field-ref (field-handle-desc f)) new-value)
(f new-value))]))
(define-syntax-rule (idempotent-field [id init] ...)
(begin (define id (make-idempotent-field 'id init)) ...))
;;---------------------------------------------------------------------------
(struct temperature (unit value) #:prefab)
(struct set-temperature (unit value) #:prefab)
(spawn (idempotent-field [C 0] [F 32])
(begin/dataflow (F (+ (* (C) 9/5) 32)))
(begin/dataflow (C (* (- (F) 32) 5/9)))
(assert (temperature 'C (C)))
(assert (temperature 'F (F)))
(on (message (set-temperature 'C $v)) (C v))
(on (message (set-temperature 'F $v)) (F v)))
(spawn (on (asserted (temperature $unit $value))
(printf "Temperature in ~a is ~a\n" unit (exact->inexact value))))
(spawn (on (asserted (observe (set-temperature _ _)))
(send! (set-temperature 'C 20))
(send! (set-temperature 'F 90))))