I was wondering the other day – how much does it cost to fill a swimming pool with beer?

So I wrote a short program to find out.

val length = 50 metres val width = 25 metres val depth = 9 feet val swimmingPool = length * width * feet val costOfAPint = (3.50 pounds) / (1 pints) println(f"It would cost £${(swimmingPool * costOfAPint) in pounds}%10.2f to fill a swimming pool with beer")

This is, of course, a hugely inefficient way of filling a swimming pool with beer – which, regardless of methodology, is a task of dubious merit in the first place. On the other hand, it’s a decent way to demonstrate my units of measure library for Scala.

The library povides two basic functions: it provides transparent conversions between different units, and checks dimensions to ensure that any operations are valid. For example, if you want to know how many gallons there are in an inch of rainfall on a hectare:

println(s"An inch of rainfall on a hectare is ${(1 hectares * 1 inches) in gallons} gallons of water")

But if you forget the inches:

println(s"An inch of rainfall on a hectare is ${(1 hectares) in gallons} gallons of water")

Well, then, that’s an error. What type of error depends on which version of the library you’re using: there’s a dynamic and a static implementation. The static version would give you a type error at compile time, whereas the dynamic version would give you a DimensionMismatchException at runtime.

Obviously, these code snippets are extracts, not full programs – the full swimming pool program (using the dynamic library) reads as follows:

import com.writeoncereadmany.unitsofmeasure.dynamictypes.units.Sterling._ import com.writeoncereadmany.unitsofmeasure.dynamictypes.units.Length._ import com.writeoncereadmany.unitsofmeasure.dynamictypes.units.ImperialLength._ object DynamicSample { def main(args: Array[String]) { val length = 50 metres val width = 25 metres val depth = 9 feet val swimmingPool = length * width * depth val costOfAPint = (3.50 pounds) / (1 pints) println(f"It would cost £${(swimmingPool * costOfAPint) in pounds}%10.2f to fill a swimming pool with beer") } }

A statement like `val length = 50 metres`

will give you a Quantity, which knows both how big it is (50 metres) and what dimensions it has (length). You can perform arithmetic on it (add/subtract it from other Lengths – trying to add or subtract it from, for example, an Area or a Time would result in an error), but in order to get a numeric value back out of it, you need to specify what units you want (and if the units don’t match the quantity, you get an error).

All you need to use the library is to import the appropriate dimension objects. Length, for example, includes a selection of units of length (including metres and feet), units of higher-order lengths (such as areas, volumes – including pints), and the implicit conversions to allow declarations like `50 metres`

.

In order to extend the library – to add your own units, for example – you need to know a little about how it works. That’s coming in part 2…

## 5 thoughts on “Ruminations on a system of units of measure in Scala, Part 1: Presented Without Comment”