patternMinor
Critique my Clojure "Game of Life" code
Viewed 0 times
critiqueclojurecodegamelife
Problem
I'm a Clojure n00b (but am experienced with other languages) and am learning the language as I find time - enjoying it so far, though the strange dreams and accidental use of parenthesis elsewhere (e.g. Google searches) are a bit disconcerting!
Usually when learning a new language the first thing I do is implement Conway's Game of Life, since it's just complex enough to give a good sense of the language, but small enough in scope to be able to whip up in a couple of hours (most of which is spent wrestling with syntax). I did this with Scala a while back, and really appreciated the comments I received.
Anyhoo, having gone through this exercise with Clojure I was hoping to get similar feedback on my efforts so far?
I'm after any kind of feedback - algorithmic improvements, stylistic improvements, alternative APIs or language constructs, disgust at my insistence on checking argument types - whatever feedback you've got, I'm keen to hear it!
```
;
; Copyright (c) 2012 Peter Monks (pmonks@gmail.com)
;
; This work is licensed under the Creative Commons Attribution-ShareAlike
; 3.0 Unported License. To view a copy of this license, visit
; http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to
; Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
; 94041, USA.
;
(ns ClojureGameOfLife.core
(:use clojure.set))
(defrecord Cell [^Integer x ^Integer y])
(def block #{(Cell. 0 0) (Cell. 1 0)
(Cell. 0 1) (Cell. 1 1)})
(def beehive #{ (Cell. 1 0) (Cell. 2 0)
(Cell. 0 1) (Cell. 3 1)
(Cell. 1 2) (Cell. 2 2)})
(def blinker #{(Cell. 0 0)
(Cell. 0 1)
(Cell. 0 2)})
(def glider #{ (Cell. 1 0)
(Cell. 2 1)
(Cell. 0 2) (Cell. 1 2) (Cell. 2 2)})
(defn flat-map
"Maps the function to the given set, returning a new set (flattened, in the case where f itself
return
Usually when learning a new language the first thing I do is implement Conway's Game of Life, since it's just complex enough to give a good sense of the language, but small enough in scope to be able to whip up in a couple of hours (most of which is spent wrestling with syntax). I did this with Scala a while back, and really appreciated the comments I received.
Anyhoo, having gone through this exercise with Clojure I was hoping to get similar feedback on my efforts so far?
I'm after any kind of feedback - algorithmic improvements, stylistic improvements, alternative APIs or language constructs, disgust at my insistence on checking argument types - whatever feedback you've got, I'm keen to hear it!
```
;
; Copyright (c) 2012 Peter Monks (pmonks@gmail.com)
;
; This work is licensed under the Creative Commons Attribution-ShareAlike
; 3.0 Unported License. To view a copy of this license, visit
; http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to
; Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
; 94041, USA.
;
(ns ClojureGameOfLife.core
(:use clojure.set))
(defrecord Cell [^Integer x ^Integer y])
(def block #{(Cell. 0 0) (Cell. 1 0)
(Cell. 0 1) (Cell. 1 1)})
(def beehive #{ (Cell. 1 0) (Cell. 2 0)
(Cell. 0 1) (Cell. 3 1)
(Cell. 1 2) (Cell. 2 2)})
(def blinker #{(Cell. 0 0)
(Cell. 0 1)
(Cell. 0 2)})
(def glider #{ (Cell. 1 0)
(Cell. 2 1)
(Cell. 0 2) (Cell. 1 2) (Cell. 2 2)})
(defn flat-map
"Maps the function to the given set, returning a new set (flattened, in the case where f itself
return
Solution
Some quick points / ideas:
Also take a look at these neat Game of Life implementations:
- The code looks pretty decent overall for a first attempt at Clojure, and you have made good use of the "functional" style. Nice work!
- You have used a
defrecordfor the cells data structure. This isn't really buying you anything, since you can just use a vector e.g.[1 2]or a map e.g.{:x 1 :y 1}directly. I'd probably use a vector: more lightweight, shorter and therefore more readable, it's clear in the context that it it is an [x y] vector.
- This min-x, min-y, x-values etc. functions add a lot of lines of code but are extremely short functions. I'd probably be more tempted to do these inline, especially since they are only used once or twice.
Also take a look at these neat Game of Life implementations:
- http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/
- http://programmablelife.blogspot.sg/2012/08/conways-game-of-life-in-clojure.html
- https://github.com/mikera/clojure-golf/blob/master/src/main/clojure/clojure-golf/examples/life.clj
Context
StackExchange Code Review Q#17603, answer score: 5
Revisions (0)
No revisions yet.