Created
May 30, 2011 10:08
-
-
Save amtal/998684 to your computer and use it in GitHub Desktop.
Conway's Life in Lisp Flavored Erlang...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; 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