Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Conway's Life in Lisp Flavored Erlang...
;;; Global clock implementation of Life.
(defmodule life_sync_cell
(export (start_link 1) (set_neighbours 2) (tick 1)
(init 1) (handle_cast 2))
(using gen_server)
(behaviour gen_server))
(include-file "deps/lfe_utils/include/using.lfe")
;;; Exported:
;; Start a cell process and gets its pid.
(defun start_link (am-alive)
(gen_server:start_link 'life_sync_cell
(tuple am-alive (self))
'[]))
;; Tell cell about neighbouring pids.
(defun set_neighbours (pid ns)
(gen_server:cast pid `(add-ns ,ns)))
;; Global time step.
;;
;; Triggers a single alive|dead message to controller.
(defun tick (pid)
(gen_server:cast pid 'tick))
;;; Internals:
(defrecord state
life ; 'dead|'alive
master ; who to report life to
(ns '[]) ; known neighbour pids
(ns-alive 0) ; how many are alive
(ns-heard 0) ; how many checked in this time step: can not
; progress until all neighbours are heard
(tick-pending 'false))
(defun init
(((tuple am-alive master))
(tuple 'ok
(make-state life (if am-alive 'alive 'dead)
master master))))
(defun handle_cast
((`(add-ns ,ns) st) ; initialization
(broadcast st `(n-status ,(st-life st)))
(tuple 'noreply (set-st-ns st ns)))
((`(n-status ,x) st) ; neighbour alive/dead info
(let* (((st) (set-state st ns-alive (+ (count-change x) (st-ns-alive st))
ns-heard (+ 1 (st-ns-heard st))))
((st) (if (and (st-tick-pending st) (all-heard st))
(timetick st)
st)))
(tuple 'noreply st)))
(('tick st) ; global timestep request
(tuple 'noreply
(if (all-heard st)
(timetick st)
(set-st-tick-pending st 'true)))))
;; Step automaton.
(defun timetick (st)
(let* (((life) (: life is-alive (st-ns-alive st)))
((st) (set-state st ns-heard 0
ns-alive 0
tick-pending 'false
life life))
((pid) (self)))
(! (st-master st) (tuple 'life pid life))
st))
;; Broadcast a message to neighbouring cells.
(defun broadcast (state msg)
(lc ((<- n (st-ns state)))
(gen_server:cast n msg)))
;; Test if all neighbours reported their state yet.
(defun all-heard (st)
(== (st-ns-heard st)
(length (st-ns st))))
;; Neighbour count inc/dec.
(defun count-change
(('dead) 0)
(('alive) 1))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.