Effective Blocks

One of the cool features in Gosu is closures, colloquially known as “blocks”. Blocks act kind of like inline function definitions, allowing you to plug bits of logic into other algorithms. (One my standard lines in the talks is “Classes are a tool for generalizing concepts, blocks are a tool for generalizing algorithms.” Pithy and, hey, maybe even true.)

Trying to describe blocks in general terms doesn’t appear to be a great way to explain them: people get lost in the terminology and syntax. The way that I finally “got” blocks wasn’t by staring intently at a text book or wiki page, it was by seeing them in action.

In this vein, I’m going to describe some common programming problems you might face and then show you how blocks can help you solve them elegantly. I hope this will help you understand blocks in Gosu and how use them effectively.

“I’ve got a List of X and I need a List of Y”

This is perhaps the classic problem that blocks can help solve:

  • “I’ve got a list of Claims, and I need a list of Claim IDs.”
  • “I’ve got a list of Employees, and I need a list of last names.”

To address this problem, Gosu has added the map() function to Iterable objects. Taking the two examples above, you can write this code:

  var ids = claims.map( \ c -> c.ID )
  var lastNames = employees.map( \ emp -> emp.LastName )

The block is the funny little thing starting with a ‘\‘. Between the ‘\‘ and the ‘->‘ are the arguments to the block (remember, blocks are kind of like a mini-function) and after the ‘->‘ comes the body of the block.

Taking a look at the first line in the code example, we have a block that takes an argument c of type Claim (Gosu infers this type) and that returns the ID of that claim.

The map() function then uses this block to run through all the claims in the claims list and create a new list, filled with the ID’s of each claim.

Nice, eh?

Here’s another example:

“I’d like to sort List X by attribute Y”

Some concrete examples might be:

  • “I’d like to sort a list of Policies by their effective date.”
  • “I’d like to sort a list of Contacts by their age.”

Gosu has an orderBy() function for this:

  var sortedPolicies = policies.orderBy( \ p -> p.EffectiveDate )
  var sortedContacts = contacts.orderBy( \ c -> c.Age )

In Java, you might use a Comparator (and then try to remember when to return -1, 0, or 1) in conjunction with Collections.sort(). I hope you’ll agree that the Gosu above is easier to write and also reads more clearly.

The advantage of the block-based approach becomes even more glaring when you want to add secondary sort columns:

  var sortedPolicies = policies.orderBy( \ p -> p.EffectiveDate )
                                .thenBy( \ p -> p.Status )

Imagine the Java Comparator for that. Ugh.

“I’d like all the elements in List X where Y is true”

This is another classic:

  • “I’d like all the Claims that are past due.”
  • “I’d like all the Employees that are active.”

Gosu has an where() function for exactly this:

  var pastDueClaims = claims.where( \ c -> c.DueDate < Date.Today )
  var activeEmployees = employees.where( \ emp -> emp.Active )

The where() function returns a new list where any items that do not meet the criteria expressed in the block are filtered out.

Very nice.

“I’d like to split a List of X up on attribute Y”

This is a more advanced usage of blocks, but it can come in quite handy in some situations:

  • “I’d like to split a list of automobiles up based on their color.”
  • “I’d like to split my friends up by their birthday month.”

Gosu has a partition() function for this:

  var carsByColor = cars.partition( \ c -> c.Color )
  print( "All red cars: " + carsByColor["Red"] )
  var friendsByBirthdayMonth = friends.partition( \ f -> f.Birthday.Month )

The partition() function splits a list up based on the block you pass in. So, in the first line of code in this example, we split a list of cars up by their color, and get a map, where the key is a color and the value is a list of cars of that color. In the next line we print the list of cars that are red.

You could partition on any attribute: make, model, year, whatever. Blocks help generalize the operation.

Composing Methods

Gosu really starts to sing when you compose these methods:

  • “I’d like to get the ids of claims past due, ordered by the claim due date”

We can compose three methods together to solve this quite succinctly and clearly:

  var pastDueClaimIdsByDueDate = claims.where( \ c -> c.DueDate < Date.Today )
                                       .orderBy( \ c -> c.DueDate ) 
                                       .map( \ c -> c.ID ) 

The corresponding java code would be more verbose, and would probably conflate the various operations, making it more difficult to understand what the code was doing.

“Hmm, this is all data structure manipulation…”

Yep.

The sweet spot for blocks (in Gosu, at least) is in data structure manipulation. There are other areas they can come in handy (callbacks, listeners) but usually you’ll be using them to transform one data structure into another.

Personally, not a day that I’m writing java code goes by that I don’t wish I had blocks. Once you get used to them, it can be very hard to go back. I hope that this quick overview helps you use blocks effectively in your own Gosu code and have a bit more fun when you are coding.


4 Comments on “Effective Blocks”

  1. Scout says:

    This is very interesting to know. A neat explanation on the beauty of blocks.

  2. Umesha Shetty says:

    I recently started using Gosu. Even though I heard about lambda expression in the past, never used it. Now it is so hard for me to code without them. 🙂

  3. Carson:
    I’ve been using Gosu Blocks for a while now. Although it’s a rather useful construct I would consider it near cousin of method pointers rather than Closures.

    Can you site an example where Block actually captures “referencing context” (non-local variables) separating it from to method pointers in C++ (or anonymous Runnable in Java) ?

    Thanks!

  4. Carson:
    Although Gosu Blocks is an useful programming construct, I consider it close cousin to method pointers, rather than Closure.

    Can you give an example where a Gosu Block captures the “Referencing Context” (non-local variables) contrasting it to C++ method pointers or Java anonymous Runnables?

    Thanks!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s