In my last post I disassembled Mr. Harms Cellular Automaton bit by bit, showing how the use of notation as a tool for thought enabled him to write that program mentally while grocery shopping. Today I'll revisit the same problem using Clojure, demonstrating the J-effect.
The cellular automaton which works in one-dimension has a very simple behavior, despite the many rules. If you haven't yet read the explanation of the J program, now might be a good time to do so: link. (skip down to The Example)
After posting last night I wanted to review some of the other solutions to the simple cellular automaton, not looking for the code but the thoughts behind the code and I was a little surprised at one of the contributions. A much older dialect of Lisp than Clojure is Common Lisp and the solution developed therein looks like so:
(defun value (x)
(assert (> (length x) 1))
(coerce x 'simple-bit-vector'))
(defun count-neighbors-and-self (value i)
(flet ((ref (i)
(if (array-in-bounds-p value i)
(bit value i)
0)))
(declare (inline ref))
(+ (ref (1- i))
(ref i)
(ref (1+ i)))))
(defun next-cycle (value)
(let ((new-value (make-array (length value) :element-type 'bit')))
(loop for i below (length value)
do (setf (bit new-value i)
(if (= 2 (count-neighbors-and-self value i))
1
0)))
new-value))
(defun print-world (value &optional (stream *standard-output*))
(loop for i below (length value)
do (princ (if (zerop (bit value i)) #\. #\#)
stream))
(terpri stream))
(loop for previous-value = nil then value
for value = #*01110110101010100100 then (next-cycle value)
until (equalp value previous-value)
do (print-world value))
What sticks out when you read that? For me 2 very important things
And so to me this posed an even more interesting question:
Has J already shaped the way I think?
When you look at Mr. Harms solution, what do you see?
life1d=: '_#'{~ (3(2=+/\) 0,],0:)^:a:
I see this:

Being a Clojurian it's only natural that I fall back on my strongest frame of reference, which is Clojure. When I read Mr. Harms program with the references being Clojure-functions its only natural that my program will mimic Mr. Harms quite strongly and that's not a bad thing. You see J more clearly than any language I've come across expresses exactly what the problem is, and then lets the compiler worry about how to solve it.
Here's one way to solve the same problem in Clojure:
(defn life1d [s]
(let [life (iterate (fn [i]
(map #(if (= 2 (reduce + %)) 1 0)
(partition 3 1 (concat [0] i [0])))) s)
render (partial map {0 \_ 1 \#})]
(loop [iteration life]
(println (apply str (render (first iteration))))
(when (not= (first iteration) (second iteration))
(recur (next iteration))))))
I wrote it so I'm biased, but what do you think? Is the intention and algorithm coming across more clearly despite being substantially shorter with less sub-routines than the CL version?
All my blogposts having been leading up the The Manifesto and Mind Games. Together they represent the groundwork for my programming experience. I have come to treasure the way Functional Programming focuses on the what and not the how, when solving problems. I feel J is already helping me improve on the ability to clearly express the problem at hand, since J has almost no notion of how. On the J Mailing List the question was recently asked: How clear is this to you?
3435 = +/ ^~ 3 4 3 5
The first few answers all lined up with Dan Brons experience "Perfectly clear, its asking if a number is equal to the sum of its digits raised to their own power". When you wield J as a tool for describing problems, you gain the ability to be even more clear than what is possible with the english language and the english language is abundantly more clear than an imperative program. Your mileage may vary, but for me its starting to look like it will be a valuable tool to first outline a problem description in J then converting to Clojure for use in production.
If I've caught your attention, please read the rest of Mr. Brons reply: here