Finite Improbability

Just programming and math, no spontaneously jumping undergarments

Picnic Invasion! Day 8 … A break for some Clojure

More fun playing around and not getting much done. I’m in the middle of finals week, so I’m trying not to get too involved with this.

Today’s current bit of playing around was at embedding the Clojure language in a Slick application. It wasn’t too hard to copy from the language’s repl implementation and make sure it wouldn’t block the thread waiting for input. After a bit of tinkering I came up with a class that does what I need, although I highly suspect that it isn’t thread-safe. Here it is:

import clojure.lang.*;
import clojure.lang.Compiler;

import java.io.InputStreamReader;
import java.io.OutputStreamWriter;


public class ClojureInteract {

    static final Symbol REFER = Symbol.create("clojure", "refer");
    static final Symbol QUOTE = Symbol.create("quote");
    static final Symbol CLOJURE = Symbol.create("clojure");

    Object EOF = new Object();

    public ClojureInteract() {
    try {
        RT.init();
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    }


    // Evaluate the current contents of system input
    public Object eval() {
    Object ret = null;
    try {
        if(System.in.available() != 0) {
        java.io.PushbackReader rdr = new java.io.PushbackReader(new InputStreamReader(System.in));
        Object r = LispReader.read(rdr, false, EOF, false);
        if(r != EOF)
            ret = Compiler.eval(r);
        }
    }
    catch(Throwable e) {
        e.printStackTrace();
    }
    return ret;
    }

    // Evaluate the given string
    public Object eval(String s) {
    Object ret = null;
    try {
        java.io.PushbackReader rdr = new java.io.PushbackReader(new java.io.StringReader(s));
        Object r = LispReader.read(rdr, false, EOF, false);
        if(r != EOF)
        ret = Compiler.eval(r);
    }
    catch(Throwable e) {
        e.printStackTrace();
    }
    return ret;
    }

    // Load the file specified by s
    public void load(String s) {
    try {
        Compiler.loadFile(s);
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    }
}

Not too bad, eh? By the way, aren’t checked exceptions ugly? Anyways, this works out pretty well in that I can pass in direct strings, tell the class to read straight from standard input, or load a file. Running my game as an inferior lisp under emacs is a simple matter of typing ”C-u 1 C-c C-z ant -e -f /Users/ajones/programming/games/clojure-picnic/build.xml run”, what could be simpler? Seriously though, I need to figure out how to set this automagically.

At this point though, I’m happy that I can pipe new function definitions straight into my game as it’s running and have them rebound on the fly. Now modifying game behavior is a simple matter of pausing, updating a definition, and unpausing.

For anyone who’s been following this series you might have noticed a conspicuous absence of information about Scala. I’m seriously considering switching from it to Clojure just for this behavior. I’m sure Scala is capable of what I want somehow, but Clojure has the distinct advantage of being a Lisp and having built-in Emacs support for this since the dawn of time. The relatively tiny .jar file (360K vs 2M) is a bonus too. I like Scala, but I don’t think it’s a great fit for this project and the direction my development practices are heading.

No comments yet. Be the first.

Leave a reply