It's always ironic to me that people think implicits reduce code clarity, and yet those same people use runtime DI frameworks and possibly AOP. Scala implicits can in my opinion be thought of as a simple compile-time lexically-scoped DI framework. It's very much a compile-time equivalent of the @Autowired or @Inject annotation in runtime DI frameworks, except it has the benefit of lexical scoping.
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?
So, to start, I would say that I agree with you that I like my DI logic for my application centralized, whether it's in a single or few classes or in a single or few XML files. On the other hand, people who use @Autowired or @Inject are doing the opposite; they are scattering their DI logic throughout the application, which I very much do not prefer.
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 haven't used implicit scopes in Scala, but after watching a demo of them, I think it's a feature that can easily be abused and cloud code clarity. Scala more than almost any other language in it's class seems particularly full of such features.
I'd love to hear from some seasoned Scala folk: what do you think of these new features?
I'm not quite seasoned, but I recognize that this discussion regularly gets muddied because it conflates implicit parameters and implicit conversions.
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.
I understand the distinction and don't like implicit parameters.
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.]
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.