Implicit Scope and Implicit Resolution in Scala
geekabyte.io
geekabyte.io
The great thing about implicits is that errors occur at compile-time and your IDE can give you all the information you need to understand what implicits are in play. On the other hand, there is no tool in the world that will save you from a complex spring-based application with strange initialization order errors, certain features silently not working for who knows what reason, and often barely-comprehensible stacktraces.
My question then would be is there any convention of where to create all these implicits?
In the old xml spring world (with it's proc and cons) I knew I could locate the creation and injection of my dependencies in a single xml, which was fully dedicated for object creation and injection, so it was very organised, and enforced all developers to work the same way.
How would I look at a codebase and understand if there is are clear places where the objects (implicits) are created and, how do I override them in tests? Do I need to invent all this, or follow a convention? How do I understand the structure of dependencies in the project?
spring xml enforced me to do it in a certain way and enforced everybody to do it in a certain way which was great, any project I opened I new what was happening at least in DI prespective.
And then I would ask what about the cake pattern in scala for a kind of dependency injection? I mean would you prefer one of them for dependency injection? or is it relative to the case you work at?
That said, the DI analogy breaks down a little bit when you consider that Scala implicit resolution happens at compile-time and is lexically scoped. As such, you can't override implicits that are created/resolved in other source files without editing those source files directly. You can only affect the implicits in your source files by using imports or defining implicit overrides.
If you want a full-blown compile-time DI framework with centralized logic in a single location, then Scala's MacWire library seems to be the best example: https://github.com/adamw/macwire
Scala's implicits can be seen as some kind of lightweight DI system, but it is definitely not meant to be used to wire together an application at the top-level.
I'd love to hear from some seasoned Scala folk: what do you think of these new features?
Implicit parameters are everywhere, and they're relatively simple to understand once you get past the mental block that your variables might not actually be declared in the file of code you are viewing. Your mental model just has to include what that file imports, and then you can pretty much understand what implicit parameters are doing. Implicit parameters are useful for a basic form of dependency injection, and they're one of the basic prerequisites for when you are using actors or futures.
Implicit conversions are something else - I wouldn't use them just to be clever.
But once you get into things like typeclasses (which are easier to understand in Haskell for some reason), implicits become important. So if you have reason to use typeclasses (and there are very good reasons to use them), then implicits are valuable.
If your programming doesn't need much abstraction, then you don't really need those kinds of tools though.
Coming from Clojure, one could say that the "use" keyword shares a lot of the same pitfalls as implicit parameters, in that you are introducing values into your namespace which have not explicitly been referenced or scoped.
In Clojure, I choose "require" instead of "use" because "use" introduces too much ambiguity. The "use" statement in Clojure consistently makes code harder to read (for me), and I suspect the same is true of Scala's implicit parameters.
[Edit: Rails is another great example of implicit parameters run amok. Needless to say, I'm not a Rails fan.]