https://kotlinlang.org logo
#language-proposals
Title
# language-proposals
d

Derek Peirce

10/06/2019, 8:45 PM
Proposal: the ability to use
by
on constructor arguments for delegation.
Copy code
class Foo(val bar by Lazy<Bar>) { ... }
would be syntactic sugar for
Copy code
class Foo(barProvider: Lazy<Bar>) {
    val bar by barProvider
    ...
}
This pattern appears over a thousand times in the codebase I'm working on, and cutting out the declared
barProvider
middle-man would make switching between
Bar
and
Lazy<Bar>
extremely simple.
👍 2
d

Dico

10/07/2019, 11:40 AM
Why does your codebase use this pattern so much? How is
bar
used, is it typically encapsulated or is it public?
d

Derek Peirce

10/08/2019, 2:28 AM
We use Dagger2, and part of that involves injecting
Lazy
and
Provider
dependencies so that the build graph can be constructed lazily, both of which have
getValue
extension methods. These would typically be `private val`s, with rare exceptions.
e

elizarov

10/08/2019, 2:45 PM
May I suggest the idea that maybe Dagger2 needs some new feature so that you would not have to use this pattern over and over?
d

Derek Peirce

10/09/2019, 6:37 AM
Like what? (Specifically possible within Java, as Dagger2 isn't Kotlin-specific.) Dagger2 is functional, and
Lazy
is precisely the way to add lazy evaluation of dependencies. We could put many
get()
calls in the codebase, but then switching between
Lazy<Bar>
and
Bar
, which the framework can accept interchangeably thanks to its code generation, would also require adding or removing every
get()
. Delegation makes that step simpler, but then we arrive at the pattern above, which still has some boilerplate that could very easily be avoided if one more use of
by
were added. Do you think the proposal would do more harm than good, or over-burdens the language? Or are you just considering alternatives?
d

Dico

10/11/2019, 9:59 PM
I think it's about the use case and how many users have it
If you're using dependency injection like this, you might as well pass the di container to the constructor
Then you simplify the pattern
private val bar by container.lazy<Bar>()
d

Derek Peirce

10/17/2019, 8:22 AM
That alternative setup would not handle qualifier annotations, and would have to be in part resolved at runtime instead of at compile-time, making it significantly less efficient. It would also require unit tests on Dagger-built classes to create their own container, instead of more naturally passing in constructor arguments, and would make it much more difficult to modify a class to be created via constructor arguments instead of via Dagger.
4 Views