Adam Warski

20 Jan 2015

MacWire 0.8.0: towards 1.0, tagging, anonymous functions support

dependency injection
macwire
scala

A couple of days ago MacWire 0.8.0 got released. It contains a couple of changes and new features. But first, I’d like to thank Marcin Kubala for his contributions.

All of the changes are reflected in the guide to DI in Scala.

Tags/qualifiers

If you have multiple objects of the same type which you want to use as dependencies, you need to somehow differentiate between them if you want wire to work (otherwise you’ll get a compile-time error). This can be now done with tags, inspired by the work of Miles Sabin:

class Berry()
trait Black
trait Blue

case class Basket(blueberry: Berry @@ Blue, blackberry: Berry @@ Black)

lazy val blueberry = wire[Berry].taggedWith[Blue]
lazy val blackberry = wire[Berry].taggedWith[Black]
lazy val basket = wire[Basket]

X @@ T is type X tagged with tag T. The x.taggedWith[T] method is available on any type. Tags don’t have any runtime overhead, they are a purely compile-time construct.

As a bonus, your code will be more type-safe, as you won’t be able to use incorrectly tagged instances where a tag is required: tags follow the expected subtyping rules, so you can upcast a tagged instance to an untagged one, but you can’t cast an instance with one tag to an instance with another tag.

Wiring with anonymous function parameters

This feature is especially useful when creating factories. Before, wiring only took into account values from the enclosing method parameters, enclosing trait/class/object and parents. Now, parameters of any enclosing anonymous functions are taken into account as well, allowing to write for example the following:

class TaxCalculator(taxBase: TaxBase, )

lazy val taxCalculator = (taxBase: TaxBase) => wire[TaxCalculator]

wireImplicit

Finally, there’s a new variant of wire: wireImplicit. When looking up values for a given constructor parameter, in addition to the usual lookup steps, an implicit lookup on the type is done. If this yields multiple values, a compile-time error is reported.

Note that if a parameter list is marked as implicit, an implicit lookup is done both for wire and wireImplicit. The difference with wireImplicit is that it makes all parameters behave as if they were marked as implicit.

Changes

MacWire no longer does by-name parameter matching for enclosing method parameters. This was a special-case which we think was rarely used (if at all), and only caused confusion.

Summing up

The 0.8.0 release will be the basis for a future 1.0 release. Exactly when 1.0 is released depends on bugs reported (or lack thereof) and user feedback on the new features. So if you are using MacWire, please try updating and let us know if there are any problems!

comments powered by Disqus

Any questions?

Can’t find the answer you’re looking for?