32leaves.net

The TI92+ just became better

After having uLISP in a sort of working state (despite the quite enormous memory leakage problem), I started to port uLISP to the TI92+ calculater (having it become tiLISP in the process). The code is in the TI92+ branch of the uLISP SVN (remember, username and password is: guest).
Below is a screenshot just showing it running (I know, not that spectacular ;-) )
tiLISP screenshot

Be aware that this code is pretty much unstable (I had to reset my TI about 10 times today), but it’s a nice prove of concept anyway.

uLISP

As the rising amount of posts per unit of time shows: I got a loot of spare time to waste these days. This is mostly because we’re writting exams these days and constant learning simply doesn’t work out. So I had to get another project.
A short while ago I bought myself a TI92+ for the math exams. Just after it arrived and I had it connected to my computer I thought: “wouldn’t it be cool to have LISP on that thing”. So I started writing:

uLISP

Roughly two days later there is the first kinda releasable version of this neat little interpreter. It’s pretty much complete when it comes to features, but there are still some more things to do:

  1. Get rid of all the memory leaks
  2. Add the
    1
    recur

    keywork to allow anonymous recursion

  3. Port it to the TI92+

So, in case you want to have a look at it: here you go … the code is published under the terms of LGPL, so feel free to do with it whatever you like. But if it becomes SkyNet don’t blame me :-)

The a2 automaton and Clojure

Clojure

During the preparation time for my exams I wanted to do something else than just learning. So I decided to give functional programming a try. The language of choice was Clojure. It’s a LISP written specifically for the JVM. This language got some pretty neat features (taken from wikipedia):

  • Dynamic development with a read-eval-print loop
  • Functions as first-class objects with an emphasis on recursion instead of side-effect-based looping
  • Provides a rich set of immutable, persistent data structures
  • Concurrent programming through software transactional memory, an agent system, and a dynamic var system
  • Compatibility with Java: Clojure can natively call methods and create objects from any Java library, and Java programs can call Clojure functions
  • Clojure is a compiled language producing JVM bytecode

To try this thing out I decided to implement the a2 automaton described a few posts before (those neat picture and the videos, etc.). So below is the code for the automaton. If you’re able to read/understand LISP this should be (hopefully) understandable :-). Especially the

moore-aliveness

function is really neat.

All in all it took me about 8 hours to write this code. Functional programming is a completely new world. Especially that we’re mostly working with immutable data here. That’s also the cause for this code being propably pretty slow. My use of recursion here is most likely not the way that is supposed to be done in Clojure. Anyway it was a fun experience and broadened my (programmers) horizon.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
(def WORLD_WIDTH  800)
(def WORLD_HEIGHT 600)

(def setup
    (map (fn [x] (vec (range WORLD_HEIGHT)))
        (vec (range WORLD_WIDTH))))

(defn init ([field]
    (concat
        (vector (map (fn [x] (rem x 2)) (first field)))
        (map (fn [x] (map (fn [y] 0) x)) (rest field))
    )
))

(defn moore-aliveness ([field x y]
    (let [n (vector [-1 -1] [ 0 -1] [ 1 -1]
                            [-1  0]         [ 1  0]
                            [-1  1] [ 0  1] [ 1  1])]
                ((fn [a i] (do
                    (let [rem (rest  i)
                                cev (first i)
                                row (nth field (+ y (nth cev 0)) [])
                                col (nth row   (+ x (nth cev 1)) 0)
                                b   (+ a col)]
                    (if (nil? rem) b (recur b rem))))) 0 n))
))

(defn nextgen-for-row ([field row x y result]
    ;(println (str x "x" y ": " row))
    (let [nx (inc x) rr (rest row) cr (first row)]
        ;(println (str "[" x " " y "] " cr))
        (let [
            nr (if (== (moore-aliveness field x y) 2) 1 0)
            nresult (conj result nr)]
            (if (nil? rr) nresult (recur field rr nx y nresult))
        )
    )
))

(defn nextgen (
    [field] (
        (fn [f y r] (let [ny (inc y) nf (rest f) cf (first f)]
            (let [nr (concat r (vector (nextgen-for-row field cf 0 y ())))]
                (if (nil? nf) nr (recur nf ny nr)))
        )) field 0 ()
    )
))

(def ng (nextgen (init setup)))
Fork me on GitHub