Thursday, April 21, 2011

Deceiving yourself in Scala

I found a cool way to trip myself in Scala today. This is what I meant:
private val lockByKey = new java.util.concurrent.ConcurrentHashMap[Any, Object]
...
locks.get(key)
This is what I actually typed:
private def lockByKey = new java.util.concurrent.ConcurrentHashMap[Any, Object]
...
locks.get(key)
Because I put 'def lockByKey' instead of 'val lockByKey' I created myself a function that creates a new ConcurrentHashMap every time it gets called instead of a single instance. Scala allows leaving out brackets in many cases so code like lockByKey.get(...) compiled fine, but as every access was creating a new map things didn't work entirely correctly.

Thankfully unit tests of basic functionality (eg ability to get the same value back twice) caught that something was awry and I was able to identfy that I had cleverly created a factory function rather than a static instance. Thank god for unit tests ;)

2 comments:

Quartz said...

I think that's a feature of scala, having the namespace and syntax of defs and vals the same, so you can start with a val, and without changing any of the client code, transform it into a function that calculates what you need. Or maybe, like your case, start with a def and decide it can be optimized by calculating it only once, turning it into a val.

Unknown said...

That a nullary method def and a val have the same usage syntax comes from the Uniform Access Principle. It's very useful as it allows encapsulation of whether a property is stored or derived at runtime.

Post a Comment