Two Guys Arguing

rock smashes scissors

Posted in haskell by youngnh on 01.27.10

as simple as A -> B -> C

So, almost two months ago I issued a challenge to Ben to implement a silly spec of a problem I had recently been playing around with. The response and the knowledge I got out of this has been tremendous.

Kevin Berridge wrote an implementation.
Josh Schramm started his own fork.
Ben, my co-blogger, wrote his own implementation.
Heath Borders wrote an implementation and then gave a fantastic presentation on his solution, which sparked a lot of discussion amongst some very smart folks at our office.

I first implemented this in Haskell. It took me a shade under 2 hours and came in at 100 lines of code even. Prodding from the peanut gallery on twitter eventually led me to cut even that number by 25 lines.

To my eye, the solution that I came up was eminently readable, flexible, and precisely solved the problem with no bloat. What amazed me more, was that this was my first try at the problem. I’ve produced code I fell in love with on more than one occasion and in more than one language, but never on the first try. Something about Haskell made turning thoughts and words into working software immensely easy.

I think it is Haskell’s type declarations. Originally, before anybody else had written their implementations, I conceived of this challenge as a way of showing how cool and natural and easy it is to go from a series of type declarations to a fully working program. This was my thought process while writing my Haskell RPS:

The two basic datatypes are Player, which is a container type for a name, and Throw of which there are Rock, Paper and Scissors specializations. Everything else comes from that.

A Haskell type declaration looks like this:


A -> B -> C

This declaration describes a function that takes a type A, a type B and returns a type C.

If you want to display a message to the user? Haskell has a type signature for that:


String -> IO ()

The IO () part is a peculiarity of Haskell’s purity. It basically says that nothing is returned, that’s the () part, but that input and output have been performed, that’s the IO part.

Now, say you want to read that string back into an object your program can use?


(Read a) => String -> a

This signature says that given a String, the function will return a type that implements the Read typeclass. Read is most like a Java interface, but the function implementing this type declaration would utilize it using techniques more akin to Java generics.

Those two functions can then be combined into a function that takes a prompt string and returns an object:


(Read a) => String -> IO a

What the above signature says is that, given a string, this function will perform IO and return any type that implements Read. Exactly which type that is depends on the context the function is used in. That the same function depending on how it is used can return any conforming datatype, is the true power of generics and type inference.

This signature really encompasses the first couple of lines of the spec. By implementing the Read typeclass for Player and Throw, we can now prompt the user and get back Player and Throw objects that we can then go on to do processing with. Being able to prompt and read in responses gets us halfway through the spec. Halfway!

What’s left is to define when a player has won and to play the game until that situation occurs. There are a couple of ways you could choose to determine a winner, but my type signature would look like this:


(Player, Integer) -> (Player, Integer) -> Maybe Player

Which says that given a tuple for each player and their score, you may or may not be able to return a winner. The cool part is that the “may not” part is the same type as the “may” part, which makes handling each case super-explicit and easy to follow.

With how to win the game in place, finally, it is time to implement the overall game. Here’s the signature I came up with:


WinLogic -> (Player, [Throw]) -> (Player, [Throw]) -> Player

I called the operation of determining a winner WinLogic. This says that if you can pass in a WinLogic object and a tuple of each player and all of their throws, then you can finally return a winning player. You’re thinking, wait, how can you pass in all of a player’s throws if they won’t have given them to you until the game’s over? Well, that’s where Haskell’s lazy evaluation makes things easy, but it’s really no more magic than passing an Iterator object in Java.

With a few extra flourishes, the Haskell implementation is done. This is the post that I had written in my mind when I first issued my co-blogger the Rock Paper Scissors challenge. Of course, what happened after made things a bit messier, and there’s some other interesting lessons to learn from everybody else’s efforts, so I’ll cover some of the ensuing happenings in later posts.

hold my code for a second…

Posted in git by youngnh on 01.25.10

add, stash, edit, apply and reset

This is mostly a note on how I work with git. A lot of people used to subversion wonder why I’m so enamored of Linus Torvald’s latest project and I usually only explain enough of it to convince them that git is an elaborate and complicated tool for replicating a subversion workflow. This is a good example of a situation in which svn would fail you.

I try as much as possible to create a new branch every time I decide to work on a new unit of work. Oftentimes, I will just absent-mindedly start coding and be 4 or 5 commits deep before realizing that I forgot to branch (which is a situation git has tools to fix as well), but for this particular stretch of coding I was on a clean branch without any untracked files.

Shortly after starting, I found myself with 4 classes, none of which compiled. In a minimalist vein, at home I work with only emacs and ant when hacking on Java code. ant can cause a bit of scroll blindness when your code has compile errors, and the situation is only exacerbated when you don’t quite get Java generics.

One class was named WinLogicFactory, and it’s functionality was the end goal of this branch. The other 3 classes were support classes. They had resuable, general-purpose functionality that WinLogicFactory would use, but contained nothing specifically related to the application I was writing. I stole the idea of them from Haskell and the classes were named Either, Left and Right.

$ git status
# On branch winlogic_factory
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	src/com/twoguys/rps/WinLogicFactory.java
#	src/com/twoguys/util/Either.java
#	src/com/twoguys/util/Left.java
#	src/com/twoguys/util/Right.java

Before Either, Left and Right were fixed and compiling, I couldn’t fix WinLogicFactory, which would use them. A bit counter-intuitively I added WinLogicFactory to the index. This allowed me to stash my current index. That left only the generic classes in my working tree:

$ git add src/com/twoguys/rps/WinLogic.java
$ git stash
$ git status
# On branch winlogic_factory
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	src/com/twoguys/util/Either.java
#	src/com/twoguys/util/Left.java
#	src/com/twoguys/util/Right.java

Once I got Either, Left and Right compiling I could now start working on WinLogicFactory, so git stash apply restored the index with my broken factory in it. I had some more work to do to get it compiling and just to convince myself that I had really gotten my workspace back to it’s original state, so I ran a git reset, which effectively pulled any uncommitted changes out of staging in the index.

$ git stash apply
$ git reset
$ git status
# On branch winlogic_factory
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	src/com/twoguys/rps/WinLogicFactory.java
#	src/com/twoguys/util/Either.java
#	src/com/twoguys/util/Left.java
#	src/com/twoguys/util/Right.java

At this point, I could fix WinLogicFactory without worrying about simultaneous errors from Either, Left and Right.

Things that are worth noting:

  • staging content in git’s index is not simply another step that you have to perform before you can commit files you’ve edited. It’s how you tell git about any file you care about.
  • git can manipulate code that isn’t committed. commits are merely a little extra information attached to otherwise generally useful structures that git was already creating for you.
Tagged with: ,

King of the nerds – Quick and Dirty Programming Contest Winners

Posted in Uncategorized by benjaminplee on 01.24.10

Winning a vendor sponsored timed programming contest at a three day technical conference (CodeMash**) which you voluntarially traveled to in Northern Ohio in the middle of January is a double edged sword.

One the one side you are the king of the nerds.
On the other side …  you are the king of the nerds.

A few weeks ago Josh Schramm, Kevin Berridge, and I (all past Dayton Flyers and college roomates) took in a great CodeMash conference and decided to enter a StoutSystems sponsored programming SmackDown just for kicks.

We won.  All hail the kings of the nerds.

Granted only ~15 teams entered (from 1 -3 people each) but none the less, we won and only one other team submitted even a failed attempt before our winning one.

Josh posted our solution in Ruby to GitHub and I have since cleaned it up a bit, added the original rules, a C# & Linq solution Kevin did while we were there and a new one of my own making in Ruby.

I am planning to write the solution in a few different languages and designs.  If anyone else has an entry or can suggest a way to make the Ruby variant any cleaner or more idiomatic … please leave me a comment or fork my repo on GitHub.

Latest Ruby variation:

lines = []

File.open('../input.txt').each { |line| lines << line }

lines = lines[1..lines.size].
              map     { |line| line.split("\t") }.
              each    { |line| line[1] = line[1].gsub(/[^a-zA-Z]/, '').reverse }.
              reject  { |line| line[1].to_s.empty? }.
              sort    { |x, y| (x[1] <=> y[1]) == 0 ? (x[5].to_f <=> y[5].to_f) : (x[1] <=> y[1]) }.
              collect { |line| line.join("\t") }.
              insert(0, lines[0])

File.open("output.txt", 'w') { |f| f.write(lines) }

** CodeMash was an absolute blast.  Great sessions, good people, nice venue, and rockin’ live music.

Long live esenihc lavivrus

Stand up sit down fight fight fight

Posted in software development by benjaminplee on 01.23.10

Prompted by a question from my good friend Kevin Berridge about agile team stand-up meetings, I quickly came up with a long list of do’s and don’ts but nothing substantial.  Nothing immediately profound.  Any quick google search can give you tips, tricks and pitfalls.  I wanted something more.  To try and ignite my thoughts I began writing down words that came to mind when I thought about a good daily standup meeting …

Wordle: daily stand up meetings

When daily standups go well, the team has a clear understanding of how they go to where they are today, where they are trying to go, and the route they are going to follow.

When daily standups go bad, individuals get frustrated, time is wasted, problems reoccur, and the meeting ends up being a means to justify paychecks and appease management.

Whether you focus your meeting on what each individual did yesterday/is doing today/is blocked by or on how the story board changed from yesterday, the real goal should be focusing the team toward a common short term goal, and making any impediments very visible. The meeting should be for the team, by the team and to the team.

Often I see standups where everyone ends up telling the PM/Scrum Master/Team Lead what they worked on yesterday and an excuse about not yet knowing what they were going to do today.  Have the team talk to the team.  If what you are sharing doesn’t have value to the rest of the team, don’t share it right now.  If a detailed discussion starts between on some members of the team, wait until the standup is over.  If the meeting stops providing value at 5 minutes, stop the meeting.  If the meeting is going past 10-15 minutes, stop and have the team decide if it should continue or be broken up in favor of smaller discussions.

Daily standups are great way to get everyone on the same page, re-focus the team on the highest priority items, and lay out a quick plan of attack.  Like time-outs in the middle of a big game, they need to help bring everyone together and formulate a short term plan to victory.  Especially when King James shows up.

Tagged with:

Notes to self: Basic CVS Command Line

Posted in notes_to_self by benjaminplee on 01.19.10

Self,

Please remember next time…


To create a new module in a given repo:

export CVSROOT=:pserver:USERNAME@CVSSERVER:/PATH/TO/REPOSITORY

mkdir PROJECT

cp FILES PROJECT/

cvs import PROJECT INITIAL start

rm -rf PROJECT

cvs checkout PROJECT

And to add files recursively from a folder:

find . -type d -print | grep -v CVS | xargs cvs add

find . -type f -print | grep -v CVS | xargs cvs add

cvs commit -m “MESSAGE”

Thank you,

Self

Tagged with:
Follow

Get every new post delivered to your Inbox.