Skip to content

Instantly share code, notes, and snippets.

@teropa teropa/life.cljs
Created Nov 3, 2015

Embed
What would you like to do?
Conway's Life in ClojureScript
;; Credits:
;;
;; * ClojureScript
;; * Reagent https://reagent-project.github.io/
;; * Figwheel https://github.com/bhauman/lein-figwheel
;; * core.async https://clojure.github.io/core.async/
;; * Christophe Grand's Life implementation http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/
(ns life.core
(:require [reagent.core :as r]
[cljs.core.async :refer [timeout <!]])
(:require-macros [cljs.core.async.macros :refer [go-loop]]))
;; Initial state, the "Blinker" lifeform
(defonce state (r/atom #{[-1 0] [0 0] [1 0]}))
; Also try the "R-Pentomimo": #{[-1 0] [-1 1] [0 -1] [0 0] [1 0]}
(defn neighbors
"Given a cell, return the collection of its neighbors in every direction"
[[x y]]
(for [dx [-1 0 1]
dy [-1 0 1]
:when (not= [dx dy] [0 0])]
[(+ x dx) (+ y dy)]))
(defn next-pop
"Given a population, return the next generation of it
following the rules of Conway's Life"
[pop]
(let [all-neighbors (mapcat neighbors pop)
neigh-count (frequencies all-neighbors)]
(set (for [[cell count] neigh-count
:when (or (= count 3)
(and (= count 2)
(pop cell)))]
cell))))
(defn evolve
"Begin a process of evolution. Will swap the state
to the next generation every 100ms"
[]
(go-loop []
(<! (timeout 100))
(swap! state next-pop)
(recur)))
(defn grid
"A React/Reagent component that renders life
to an SVG element"
[]
[:svg {:width 450
:height 450
:viewBox "-225 -225 450 450"}
(for [[x y] @state]
[:rect {:width 20
:height 20
:x (* x 20)
:y (* y 20)}])])
;; Render the grid component to the document
(r/render [grid] (.-body js/document))
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.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.