enjoying salad since 1978.

Monday, July 20, 2009

Functional Refactoring #1: Replace conditional inside fold with filter.

Recently, while working on some code, I noticed that I have been making the same transform on lots of functional code in Scala. I think it's clearly a Refactoring and should have a name.

"Replace conditional inside fold with filter"

The idea is that if you're folding over items in a list and manipulating them based on a conditional, it might be clearer if you pull out the conditional and filter the list on that conditional first.

Here is a contrived example borrowed from a fake test suite. Let's say I had code with a conditional inside of a fold:

sampleUsers.values.foreach { u =>
  if (u.id != 0) {
    Authentication(u.id, u.hash).passwordToken mustEqual u.passwordToken
  }
}

Let's apply this refactoring to make the test case clearer.

sampleUsers.values.filter(u => u.id != 0).foreach { u =>
  Authentication(u.id, u.hash).passwordToken mustEqual u.passwordToken
}

This works with multiple inner conditionals as well. You can fit them into one filter or chain multiple filters together.

Even though this is a simple refactoring, it seems like a worthwhile place to start cataloging.

7 Comments:

Blogger Dave Briccetti said...

Now that’s a bite-sized Scala tip that I can use!

Perhaps you’ve already contacted the Scala IDE makers about automating this refactoring.

Lacking an expert Scala mentor sitting next to me when I code, I would sure love having my IDE propose embetterments such as this.

1:39 AM

 
Blogger Bjarte said...

What about using a for comprehension here? I think they are more readable then multiple filter/foreach.

11:16 AM

 
Blogger Steve Jenson said...

@dave more are on the way!

@bjarte Probably due to my functional background I never use for-comprehensions in my code. Sometimes they are the better choice, though.

11:21 AM

 
Blogger Villane said...

This refactoring may sometimes introduce a performance problem. So the reverse may also be useful.

2:09 PM

 
Blogger Steve Jenson said...

@Villane you're right, it's important to remember that it's O(N) complexity.

2:26 PM

 
Blogger Bram Cohen said...

What's your reasoning behind this refactoring? Is it to make the code more readable? There's a bit of a performance degredation with the second approach - because you're doing two passes over the data, if it's a large amount of data then it will have twice as many cache misses.

8:33 AM

 
Blogger Steve Jenson said...

hiya bram!

The only motivating factor is readability. If you're expecting large lists, the inner conditional will be better.

10:12 AM

 

Post a Comment

Links to this post:

Create a Link

<< Home