Chain Gang

So as my Scala journey has progressed.  It has really stepped up since I’ve switched jobs and been able to focus on it for a few weeks without distraction.  I’ve found that I’ve crossed into the functional style.  If statements annoy me now, and anything mutable causes me concern.  I was doing really well, getting the hang of things and then I ran into an issue.

Here was my use case.  I’ve got a deep domain, its heavily customized per customer in many ways.  The way I’m dealing with this right now, is that the actual field names of wide domain objects have customized labels per client.  We are talking 100 columns or more that can be customized.  I knew I needed to get all meta data with it, and use reflection, no problem, been there before.  But what I wanted to do, was read data from the store, then apply the label just in time, I don’t want to do a bunch of “select * as name from”  …, but rather get data, and then transform it.  Partially, because that would perform badly, partially because I’m going to have to transform the same data again and again, I don’t want that logic all wrapped up in the data access layer, and frankly its not available there, well yet anyway.

So that’s my use case, here’s my technical problem.  I had this list I needed to iterate over using a normal map type flow.  As I was going over that list, I was modifying some json.  What I ended up having was a nice functional map activity that had to pass in some json, and then return some json, for the next guy to transform.  It meant I had to create a var, and I found myself being annoyed greatly by this, I really wanted a val not a var.

Here is the before:

So you can see what is wrong here, looking at transform().  I’m taking an object, modifying it, and then sending it back, mutating stuff as I go.  I really wanted to pass the output of one function as input to the next function.  I knew that is what I wanted, but I wasn’t sure how to do it, and I didn’t know the right words to google.  In my mind I thought it should wind up being some like f(f(f(value))), which felt really recursive, only I’m going thru this list as I do stuff, so not really.

Then I found this blog post: http://danielwestheide.com/blog/2013/01/23/the-neophytes-guide-to-scala-part-10-staying-dry-with-higher-order-functions.html

In the middle he talks about “Composing a transformation pipeline”.  That is exactly what I needed, I wanted to pass the output from one function as the input to the next function.

So here’s how it ended up after applying that idea:

Ok so don’t worry about all the reflection the key bits are how this:

Becomes this:

Instead of taking in the JsValue object and then returning it back for the next guy to mutate, I return a function which accepts a JsValue and returns one.  So when this map activity finishes I end up with a Seq of functions.  The built in Scala Function.chain() function takes a Seqs of functions and applies the output of one to the input to the next.  From the Scala docs that business looks like this.

def chain[a](fs: Seq[(a) ⇒ a]): (a) ⇒ a

Given a sequence of functions f1, …, fn, return the function f1 andThen ... andThen fn.

So read about partial functions and composition.  I’m finding that learning the functional vernacular really helps you google stuff to find what you are looking for.  As a professional day to day programmer, what I need is to make these tools part of my everyday toolbox.  They aren’t just esoteric academic things, they are tools I can use to solve real problems, which is why I’m blogging about this, so others might see how I used this capability to solve a problem.

 

Advertisements

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