Scala Bowling, I think …

I've been working with Scala a bit, just to learn what it is. I've found it interesting, if frustrating. Here is a bowling experiment.

The bowling problem that Chet and I use for TDD demonstrations is somewhat different from the one that Bob Martin uses. Ours can be stated: “Given a list of rolls of a legal game of bowling, compute the final score of the game.” This turns out to be just big enough to be interesting and to be something we can do in about an hour, with plenty of discussion and questions.

I wrote this one in full TDD style, but I will present here only the final version, with some discussion. Mostly I spent the early part of the project trying to learn the Scala language and tools, and trying to work in what I hope is a Scala-like style. I’ll leave the article open for comments in case you’d like to advise me otherwise.

First, the Tests

Here are the tests, written in ScalaTest Spec format. I kind of like that form, as it means I don’t have to make up really weird test method names.

As always, these are shown in the order created. Nothing special here, I just create a game and expect its score. I did, of course, work one test at a time, making each one work before creating a new one.

I had a design in mind, as always. I think it is neither desirable, nor quite likely even possible, to work with no design in mind. The trick is to make no steps in the direction of the design until the code calls for them. You’ll have to take my word for it that I accomplished that. The point here is just to show you the result, which I think is interesting.

The design I had in mind is one that Chet and I tried in Java or C# last week. Under the Game object, there is a “Framer” object that steps along the sequence of rolls, positioning itself to the start of each frame, and adding the score of that frame to the game total. In Java, we wound up having that object maintain an index into the array of rolls, and it would step that index by 2 for spares and open frames, and by one for strikes. (All done one step at a time, of course.)

Now, the Game

The game didn’t change after I first refactored in a rudimentary framer. It goes like this:

Not much to see here. As I look at it now, I suspect there is a more Scala-like way to do this. If you see one, please let me know.

And, the Framer

The Framer class has gone through a number of iterations, from a procedural, indexed approach, to this more functional one. One essential idea is that this Framer, rather than indexing through the list of rolls, actually consumes it. The other idea is that at each frame position, the Framer adds together two rolls, or three rolls, to get the frame score. An open frame scores just the two rolls of the frame, while a strike scores the one roll of the frame and the next two rolls, while a spare scores the two rolls of the frame and the next one. Since 2 + 1 equals 1 + 2, both “mark” frames wind up scoring three rolls.

I first had the idea of creating a tuple saying how many rolls to score, and how many to consume or “eat”. Then I hit on using Scala pattern matching to identify which kind of frame we’re dealing with.

Here again, I’m open to comments on style, and offers of better ways of doing it.

Overall, it was a somewhat frustrating experience, but mostly this was due to trying to hook together all the tools one would need. Partly, however, I found the two books I had, Wampler’s and Venkat’s, didn’t lend themselves to my style of learning, whatever that is.

Some of that is due to the fact that I am a Windows user and prefer to use an IDE. I realize this calls my masculinity into question, but I can live with that.

Anyway, that’s my report. I look forward to your comments, and I’ll probably write a few more articles about my experience with Scala. Enjoy!

Frankly, I’m surprised by the match … apparently everything inside a case is taken implicitly as abstract parameters. Very interesting.

I couldn’t find a way to get rid of the ._1 and ._2 in the scoreFrame method: everything I tried to give those two Ints names wouldn’t compile.

As for Ilmari’s comment about the 1 to 10, I don’t see how to get rid of that either. Would like to learn more …

Another Pattern Match

I fiddled with the pattern match a bit, making it return two lists, the rolls to sum, and the rolls to work with next time. You’ll notice I’m still referring to the rolls state variable and storing over it. The scoreFrame method is simpler now: I’m not so happy with the pattern itself. Your thoughts?