Tuesday, July 21, 2009

Clojure + Bowling Kata

Just the other day (yesterday) Uncle Bob had a post about Learning Clojure. He implemented a bowling scoring kata. So Dan P. and I decided to try it ourselves, but since we're from Boston we implemented candle pin bowling rules:

As we were talking through designs for this, and as we talked about scoring frames, we realized that there were three cases:

  1. Strike – score the first ball, plus the next two ‘bonus’ balls, then remove the first ball (the strike) from the list, then continue scoring.
  2. Spare – score the first two balls, plus the next ‘bonus’ ball, then remove the first two balls (the spare) from the list, then continue scoring.
  3. No-mark – score all three balls in the frame, then remove them from the list, then continue scoring. (Remember: candlepin!)
In all these cases you want to score three balls, the only difference was in how many balls you remove from the list before you continue scoring (i.e., how many balls were in the frame you are removing from the yet-to-be-scored list). So this is what we came up with: http://github.com/zdsbs/candlepin-bowling/tree/master
(ns scorecard)

(defn third [rolls]
    (first (next (next rolls))))

(defn first-two [rolls]
    (+ (first rolls) (second rolls)))

(defn strike? [rolls]
    (= 10 (first rolls)))

(defn spare? [rolls]
    (= 10 (first-two rolls)))

(defn remove-strike [rolls]
    (rest rolls))

(defn remove-spare [rolls]
    (rest (rest rolls)))

(defn remove-normal-frame [rolls]
    (rest (rest (rest rolls))))

(defn remove-frame [rolls]
        (if (strike? rolls)
            (remove-strike rolls)
            (if (spare? rolls)
                (remove-spare rolls)
                (remove-normal-frame rolls))))

(defn score [input-rolls]
    (loop [rolls input-rolls score 0 frame-counter 0]
        (if (or (empty? rolls) (= 10 frame-counter))
            score
            (recur 
                (remove-frame rolls) 
                (+ score (first rolls) (second rolls) (third rolls)) (inc frame-counter)))))

And the tests:

(ns scorecard-test
    (:use clojure.contrib.test-is 
        scorecard))

(deftest test-third
    (is (= 3 (third [1 2 3 4]))))

(deftest test-first-two
    (is (= 3 (first-two [1 2 3]))))

(deftest test-remove-frame
    (is (= [3 4 5] (remove-frame [0 1 2 3 4 5])))
    (is (= [3 4] (remove-frame [10 3 4])))
    (is (= [5] (remove-frame [6 4 5]))))

(deftest test-remvo-two-frames
    (is (= [] 
        (remove-frame 
            (remove-frame [0 1 2 0 0 0])))))

(deftest test-scores
    (is (= 0 (score [])))
    (is (= 6 (score [1 2 3])))
    (is (= 15 (score [1 2 3 4 5 0])))
    (is (= 19 (score [10 1 2 3])))
    (is (= 17 (score [5 5 1 2 3])))
    (is (= 300 (score [10 10 10 10 10 10 10 10 10 10 10 10])))
    (is (= 19 (score [5 5 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 ])))
    (is (= 21 (score [10 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 ]))))

Also check out:
Stuart Halloway's implementation. Besides just an implementation, he has a great discussion on how to approach the problem in a functional way. (his implementation is much nicer than this one)
Uncle Bob's son over at 8th light also wrote up an implementation

Sunday, July 19, 2009

Git Commands Part I

I'm always forgetting a very useful git command, so I'm posting it here in the hopes that: a) writing it down will help me remember and b) if I forget again, at least I can just goto my blog.

git add -u
(if you're like me and you rename or delete files without calling git rm git add -u takes care of staging the changes)

and thank you Stack Overflow: git rm multiple files that have already been deleted from disk

Oh and if you're pushing a Java project into a git repository, the .git/info/exclude file is very useful to ignore all the generated .class files.

Wednesday, July 15, 2009

Block Editing in Eclipse Galileo

Eclipse now has block editing hooray!

Ummm, what's the key binding for it? There's nothing in eclipse help, nothing in cmd-shift L, too many of my google searches took me to a crappy reddit page which doesn't tell you what the key binding is. Eventually someone decided to be helpful with this post. The key binding on OS X is cmd-alt-a

Anyway, hooray for block editing. Boo for wasting time looking for the keybinding, I hope this saves someone some time.

Wednesday, July 8, 2009

Hawthorne Effect

Apparently my post on measuring things was really about the Hawthorne Effect. Which in brief is: The simple action of measuring peoples productivity will increase their productivity. If you read that article though, there are lots and lots of criticism, but I prefer the BS approach, it's a cool idea, let's run with it!

I've been enjoying trying the Pomodoro Technique and have noticed a change in my productivity. Honestly, I'm not following it strictly, I haven't even read much of the website, but I did download a little app and I'm measuring tasks. I'm guessing one of two things is a result of the change in productivity:

  1. The Hawthorne Effect has some merit and by measuring my tasks, and measuring my goofing off, I'm improving the amount of time I'm staying on task
  2. There's something about a change in process that makes you notice inefficiencies in the way you do things

For the time being I'm going to assume #1 is true :) and that the Hawthorne Effect probably isn't valid in a general sense. You can always game metrics / measurements etc. etc. But on a personal level, if the metric you're measuring is of value to you, if you don't game your own personal game, then I think those metrics do have value and the Hawthorne Effect does apply. Or at least that's the BS I'm slinging today.

This post took 30 minutes to write, I'm now taking a 5 minute break.

Tuesday, June 30, 2009

Corey Haines Visit to Icosystem

Friday the 26th was a fun day at Icosystem. Through a random chain of events Corey Haines stopped by as part of his pair programming tour. I had the opportunity to pair with him for a few hours and talk a lot of shop.

Pairing is always a fun activity and it's really fun to pair with someone you've never paired with before. Not only do you get some work done, but you get a nice view into some else's coding process, asthetic, and you always learn a few new tricks. I picked up two things from Corey that I'll be trying out:

  • When doing a refactoring, only allowing one test to be failing at a time. It's hard to do, but I liked how it felt.
  • The pomodoro technique - Work for 25 min, take a 5 min break, use a timer. I installed Pomodoro 0.24 for OS X. It puts a nice little timer in my application (what is that thing called?) bar. Maybe it's a great process or maybe it's just something new, but so far it's a nice tool and is keeping me focused. Another nice feature of it is you note what the task is you're working on. I don't know about you but I have to fill out timesheets for billing, any tool that helps with that is great!
I'm sure there were other things I picked up but they're not coming to me right now.

Because of Corey's visit I met a bunch of the Ruby folk in the Boston area. It really made me realize how lacking the Java community is in having a... community. I might have to start going to the bostonrb meetings just to hang out with folks who like to talk about coding. Maybe they won't mind having a Java hacker in their midst :P

Writing this post took me, 27 minutes, I'm terrible at the Pomodoro technique

Tuesday, June 23, 2009

The Downfall of Agile Hitler

Who knew Agile could be so hilarious: The Downfall of Agile Hitler

Also a little less funny but also great: Hitler Does Unit Testing

Friday, June 12, 2009

Learning Clojure - Calling Clojure From Java

Last night, we played with some of Clojure's interop with Java. We tried out with great success Jay Fields little example. Next up was compiling Clojure to Java class files (this was much trickier).

The documentation is pretty good and can be found at: http://clojure.org/compilation and under the (gen-class) API entry. There are two tricky bits, 1) the extra 'this' arg 2) the classes compilation directory.

But first the code sample:


(ns printer
  (:gen-class
   :methods [[printString [String] void]]
  )
)

(defn -printString [this arg]
        (println arg))

:gen-class is the directive to the clojure compiler that it should compile this .clj file into a java class. The :methods section allows us to define methods, we're defining the printString method which is a void and takes a String as it's arg.

The clojure function must begin with a '-' and then there's the 'this' arg. It took a little bit to find the 'this' gem in the documentation on the compilation entry (seriously, who reads everything before they start experimenting)

hasNext and next are implementations of methods in the Iterator interface. While the methods take no args, the implementation functions for instance methods will always take an additional first arg corresponding to the object the method is called upon, called by convention 'this' here. Note how the state can be obtained using an ordinary Java field access.

So no matter what method you expose to java it will alway have at least one arg which is the instance of the object. I can't tell you how many times we were so confused why we were getting wrong number of arg error messages when first trying this out.

Now to compile:
java -cp clojure.jar:. clojure.main -r
user=>(compile 'printer)
java.lang.RuntimeException: java.lang.ClassNotFoundException: printer$_printString__4 (NO_SOURCE_FILE:0)

This is because you didn't create 'classes' directory and add it to your classpath, it's exactly what the error says right?
create the directory, add it to your class path and try again
java -cp clojure.jar:.:classes clojure.main -r
user=>(compile 'printer)
printer

Great, hopefully there are no more exceptions, try javap on printer.class you should see something like:

zacharyshaw$ javap classes/printer
public class printer extends java.lang.Object{
    public static {};
    public printer();
    public java.lang.Object clone();
    public java.lang.String toString();
    public boolean equals(java.lang.Object);
    public int hashCode();
    public void printString(java.lang.String);
    public static void main(java.lang.String[]);
}

Now you should be all set to call through to your printer.class

public class Foo {
 public static void main(String[] args) {
  new printer().printString("hello world");
 }
}

There's loads of different things you can do, like implementing interfaces, extending classes etc. I'm really looking forward to seeing how I can integrate clojure into one of my projects (only where it makes sense of course :P )

 
Web Statistics