# Why is 'by lazy' not happy with in-construction property initialization?

**URL:** <https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184>\
**Category:** Language Design\
**Created:** [November 26, 2019, 9:05pm UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184 "2019-11-26T21:05:27Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![zsombor](https://avatars.discourse-cdn.com/v4/letter/z/4bbf92/32.png) [@zsombor](https://discuss.kotlinlang.org/u/zsombor)\
**Post date:** [November 26, 2019, 9:05pm UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/1 "2019-11-26T21:05:27Z")

</div>

```
class A {
    val y: Int
    val z: Int by lazy {
        y // ERROR: variable 'y' must be initialized -- Why?
    }
    val w: Int
        get() = y // No error!

    constructor(x: Int) {
        y = x
    }
}

```

Why do I get an error ‘variable ‘y’ must be initialized’ inside the lazy init?

[This post](https://discuss.kotlinlang.org/t/compiling-property-without-initializer-depends-on-the-way-constructor-is-declared/7225/2) looks like a different manifestation of the same issue. Is this a bug?

I am on Kotlin 1.3.50 in an Android project.

---

<div class="post-metadata">

**Author:** ![lamba92](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/lamba92/32/5089_2.png) [@lamba92](https://discuss.kotlinlang.org/u/lamba92)\
**Post date:** [November 26, 2019, 9:21pm UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/2 "2019-11-26T21:21:46Z")

</div>

Many things happens under the hood when you use delegation. The error here more conceptual than syntactic.

You are creating a class in Java style in Kotlin, and while itself is not a problem, you will need to take care of a lot of stuff that the Kotlin compiler can handle for free if you go for a more Kotlin way:

```kotlin
class A(val y: Int) {
    val z by lazy { y }
    val w
        get() = y
}

```

This way the compiler will handle any possible instantiation order problem and when the properties gets initialized you will be sure that everything is available from the constructor and ready to use.  
I’d really recommend to read the documentation about [constructors](https://kotlinlang.org/docs/reference/classes.html#constructors).

By the way, the order in which you write properties and constructors matters. Move the constructor definition up and it should work.

---

<div class="post-metadata">

**Author:** ![zsombor](https://avatars.discourse-cdn.com/v4/letter/z/4bbf92/32.png) [@zsombor](https://discuss.kotlinlang.org/u/zsombor)\
**Post date:** [November 26, 2019, 10:05pm UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/3 "2019-11-26T22:05:37Z")

</div>

I can’t use the primary constructor in the real use case. Also, I am not so much looking for an alternative solution, rather an explanation why the code doesn’t compile as written.

Moving the secondary constructor to the top doesn’t change anything.

I did read the documentation about constructors. Which part in particular addresses this issue?

---

<div class="post-metadata">

**Author:** ![fatjoe79](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/fatjoe79/32/4221_2.png) [@fatjoe79](https://discuss.kotlinlang.org/u/fatjoe79)\
**Post date:** [November 27, 2019, 11:25am UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/4 "2019-11-27T11:25:41Z")

</div>

The problem is that the compiler cannot figure out when x is accessed within the lazy’s lambda. Does lazy call the lambda immediately or at a later point. If it is immediately, the field needs a value. The compiler cannot know this. (lazy is not a language feature, it is a common API function).

In case of get() the compiler can infer from the shown code alone that it will not be invoked before initialization is completed.

---

<div class="post-metadata">

**Author:** ![zsombor](https://avatars.discourse-cdn.com/v4/letter/z/4bbf92/32.png) [@zsombor](https://discuss.kotlinlang.org/u/zsombor)\
**Post date:** [November 27, 2019, 1:48pm UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/5 "2019-11-27T13:48:11Z")

</div>

> [@fatjoe79](#):
>
> the compiler cannot figure out when x is accessed within the lazy’s lambda […] lazy is not a language feature

Thanks, this makes sense now.

The other piece of the puzzle that just fell into place for me is that “the code in all initializer blocks _including property initializers_ is executed before the secondary constructor body.” I did quote this from the constructor documentation, but I had to add the italicized part as that is not explicitly stated there. May be an opportunity for improvement, if anyone in charge of the documentation is reading this.

---

<div class="post-metadata">

**Author:** ![kushkies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/kushkies/32/7013_2.png) [@kushkies](https://discuss.kotlinlang.org/u/kushkies)\
**Post date:** [December 3, 2019, 9:02pm UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/6 "2019-12-03T21:02:57Z")

</div>

Pulled from above the 3rd code block in the constructors section: “During an instance initialization, the initializer blocks are executed in the same order as they appear in the class body, interleaved with the property initializers”

Still agree it could be more explicit and not hidden in the text

---

<div class="post-metadata">

**Author:** ![Wasabi375](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wasabi375/32/4741_2.png) [@Wasabi375](https://discuss.kotlinlang.org/u/Wasabi375)\
**Post date:** [December 4, 2019, 1:16am UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/7 "2019-12-04T01:16:20Z")

</div>

> [@kushkies](#):
>
> Still agree it could be more explicit and not hidden in the text

I’m not really sure how you want this to be otherwise. It even comes with a code example that shows the order of execution of the init blocks/property initializers. If you have a better idea of how to show that I’d be interested to see it.  
There are a few areas where the kotlin documentation is lacking, but this one is good IMO. That said if you have an idea on how to improve it, go for it. Documentation can always be improved 😄

---

<div class="post-metadata">

**Author:** ![zsombor](https://avatars.discourse-cdn.com/v4/letter/z/4bbf92/32.png) [@zsombor](https://discuss.kotlinlang.org/u/zsombor)\
**Post date:** [December 4, 2019, 3:54pm UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/8 "2019-12-04T15:54:12Z")

</div>

> a code example that shows the order of execution of the init blocks/property initializers

When I look at the sample code I posted at the beginning of this thread, I see no initializer blocks. Because of this, even though I did read through all the sample code and the part that said "initializer blocks are executed in the same order as they appear in the class body, interleaved with the property initializers”, it didn’t register at first that this part applies to me because hey, I don’t have any initializer blocks.

Same thing with “the code in all initializer blocks is executed before the secondary constructor body.” I have property initializers and a secondary constructor, not initializer blocks and a secondary constructor.

Obviously one can mentally bridge the gap and conclude that _if_ initializer blocks are interleaved with property initializers, _and_ initializer blocks are executed before the secondary constructor body, _then_ property initializers are probably also executed before the secondary constructor body.

The improvement would be to spare the reader this mental effort and have one sentence that covers all three components (initializer blocks, property initializers, and secondary constructors). Specifically, my suggestion is to add the italicized part to this sentence: “the code in all initializer blocks _and property initializers_ is executed before the secondary constructor body.”

Or if you want to get fancy, then add a code example that covers all three components at the same time.

---

<div class="post-metadata">

**Author:** ![Wasabi375](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wasabi375/32/4741_2.png) [@Wasabi375](https://discuss.kotlinlang.org/u/Wasabi375)\
**Post date:** [December 4, 2019, 4:41pm UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/9 "2019-12-04T16:41:11Z")

</div>

I just created a change to the docs here: [Clarify constructor and property initializer execution order · Wasabi375/kotlin-web-site@673f7c1 · GitHub](https://github.com/Wasabi375/kotlin-web-site/commit/673f7c13e824fdd8be4bdd92b56f3a9457a633a9?short_path=1932db2#diff-1932db2efce252203baef36826a013a4)

Unless anyone here has any more feedback I’ll finish up the PR later this evening.

---

<div class="post-metadata">

**Author:** ![Wasabi375](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wasabi375/32/4741_2.png) [@Wasabi375](https://discuss.kotlinlang.org/u/Wasabi375)\
**Post date:** [December 5, 2019, 7:11am UTC](https://discuss.kotlinlang.org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/10 "2019-12-05T07:11:42Z")

</div>

> <https://github.com/JetBrains/kotlin-web-site/pull/1527>
>
> This is a small change based on the discussion here: https://discuss.kotlinlang.…org/t/why-is-by-lazy-not-happy-with-in-construction-property-initialization/15184/8?u=wasabi375
> 
> The problem there is 
> \`\`\`kotlin
> class A {
> val y: Int
> val z: Int by lazy {
> y // ERROR: variable 'y' must be initialized -- Why?
> }
> val w: Int
> get() = y // No error!
> 
> constructor(x: Int) {
> y = x
> }
> }
> \`\`\`
> The original author missed that the initializer of \`z\` ( in this case the lazy delegate) is created before the secondary constructor \`y = x\` is executed. He suggested the change here.
