# Braces : block code and lambda confusion

**URL:** <https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954>\
**Category:** Language Design\
**Created:** [February 6, 2026, 12:56pm UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954 "2026-02-06T12:56:48Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![sylvainspinelli](https://avatars.discourse-cdn.com/v4/letter/s/0ea827/32.png) [@sylvainspinelli](https://discuss.kotlinlang.org/u/sylvainspinelli)\
**Post date:** [February 6, 2026, 12:56pm UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/1 "2026-02-06T12:56:49Z")

</div>

Starting with this example:

```kt
class A {
	var prop: A? = null

	fun doX() {
		if(prop!=null) prop!!.print()
		else println("prop is null")
	}

	fun print(){
		println("...")
	}
}

```

We are trying to eliminate the use of `!!` (NPE hunt), so we rewrite `doX()`:

```kt
	fun doX() {
		prop?.also { p ->
			p.print()
		} ?: println("prop is null")
	}

```

All is fine. Now, in the else case we need to add a second line.

With the if/else syntax we write:

```kt
	fun doXx() {
		if(prop!=null) prop!!.print()
		else {
			println("prop is null")
			println("second line")
		}
	}

```

Naturally, with the elvis we would write:

```kt
	fun doX() {
		prop?.also { p ->
			p.print()
		} ?: {
			println("prop is null")
			println("second line")
		}
	}

```

But this code is broken! The elvis right part is never called because braces means here a lambda and not a block code as with the “else” syntax.

**Subtle bug, invisible and without any warning**. Moreover this code has no sense since the two lines of codes in the lambda will never be called.

In this case, **would it be possible to add a warning with an intention to rewrite it correctly**?

The right code is:

```kt
	fun doX() {
		prop?.also { p ->
			p.print()
		} ?: run {
			println("prop is null")
			println("second line")
		}
	}

```

This will prevent us from producing erroneous code that is not easy to detect and debug.

Thanks.

---

<div class="post-metadata">

**Author:** ![kyay10](https://avatars.discourse-cdn.com/v4/letter/k/c57346/32.png) [@kyay10](https://discuss.kotlinlang.org/u/kyay10)\
**Post date:** [February 6, 2026, 1:37pm UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/2 "2026-02-06T13:37:57Z")

</div>

I believe the [return value checker](https://github.com/Kotlin/KEEP/blob/main/proposals/KEEP-0412-unused-return-value-checker.md) will give you a warning on this

---

<div class="post-metadata">

**Author:** ![Landei](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/landei/32/9407_2.png) [@Landei](https://discuss.kotlinlang.org/u/Landei)\
**Post date:** [February 6, 2026, 2:00pm UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/3 "2026-02-06T14:00:57Z")

</div>

As @kyay10 already answered the question, just as a pragmatic side-note: I found that in these situations `when` is usually better than `if,` especially as you can redefine the value as a `val` and therefore get rid of the nullability:

```
fun doX(): Unit =
    when(val p = prop) {
        null -> {
            println("null")
            println("second line")
        }
        else -> p.print()
    }

```

In my opinion, this is more readable than the Elvis version.

---

<div class="post-metadata">

**Author:** ![sylvainspinelli](https://avatars.discourse-cdn.com/v4/letter/s/0ea827/32.png) [@sylvainspinelli](https://discuss.kotlinlang.org/u/sylvainspinelli)\
**Post date:** [February 6, 2026, 4:36pm UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/4 "2026-02-06T16:36:36Z")

</div>

Unfortunately, no.

With `-Xreturn-value-checker=check` (or `=full`), a new warning is shown in `formatGreeting()` example, but no warning for the lambda never called.

 ![image](https://us1.discourse-cdn.com/flex019/uploads/kotlinlang/original/2X/7/7697db6d7e6542a8b3182c36f577b5e625aa5d9c.png)

---

<div class="post-metadata">

**Author:** ![jean.chalard](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jean.chalard](https://discuss.kotlinlang.org/u/jean.chalard)\
**Post date:** [February 10, 2026, 8:34am UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/6 "2026-02-10T08:34:20Z")

</div>

I mean, the example is very contrived ; nothing in here seems natural. But IIUC, the issue is that `?:` does not warn with `value is unused` ?

Maybe I’d showcase it with :

```auto
fun foo(ni : Int?, i : Int) {
  ni ?: i
}

```

This doesn’t warn, though certainly the value is unused, and it’s the same issue as the original post. This has nothing to do with lambdas right ?

---

<div class="post-metadata">

**Author:** ![Skater901](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/skater901/32/10163_2.png) [@Skater901](https://discuss.kotlinlang.org/u/Skater901)\
**Post date:** [February 11, 2026, 1:34am UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/7 "2026-02-11T01:34:55Z")

</div>

I think this one doesn’t make sense, because the Elvis operator is irrelevant. If you remove it, you still have a statement that does nothing. It’s only relevant if the Elvis operator confuses the compiler and makes it not realise that the statement is unused.

```kotlin
fun foo(ni : Int?, i : Int) {
  ni // <--- does nothing, does compiler warn?
}

```

```kotlin
fun foo(ni : Int?, i : Int) {
  ni ?: i // <--- does nothing, does compiler warn?
}

```

---

<div class="post-metadata">

**Author:** ![jean.chalard](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jean.chalard](https://discuss.kotlinlang.org/u/jean.chalard)\
**Post date:** [February 11, 2026, 2:41am UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/8 "2026-02-11T02:41:42Z")

</div>

Yes that was my point. The lone unused variable warns, but with the elvis it doesn’t. I think this is a much clearer version of the issue in the original post.

---

<div class="post-metadata">

**Author:** ![moddy\_te\_eni](https://avatars.discourse-cdn.com/v4/letter/m/c89c15/32.png) [@moddy\_te\_eni](https://discuss.kotlinlang.org/u/moddy_te_eni)\
**Post date:** [February 11, 2026, 8:32am UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/9 "2026-02-11T08:32:29Z")

</div>

perhaps a stupid question, but why will the lambda never be called?  
And what is the problem in `formatGreeting()` shown on the ‘+’ ?

---

<div class="post-metadata">

**Author:** ![Skater901](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/skater901/32/10163_2.png) [@Skater901](https://discuss.kotlinlang.org/u/Skater901)\
**Post date:** [February 12, 2026, 8:20am UTC](https://discuss.kotlinlang.org/t/braces-block-code-and-lambda-confusion/30954/10 "2026-02-12T08:20:23Z")

</div>

The lambda will never be called, because it’s never called. 😛

The basic problem is that the Elvis operator provides an alternative value. Let’s look at a super basic example.

```kotlin
fun aOrB(a: Int?, b: Int): Int {
    return a ?: b
}

```

In this example, we have a function that takes two Integers, and returns an Integer. One of those Integers can be null. If `a` is not null, we return `a`. If `a` _is_ null, we return `b`.

Basically, any expression (something that returns a value) can use an Elvis operator to say “if the first thing is null, then here, take this second thing”.

We could also write that example like so.

```kotlin
fun aOrB(a: Int?, b: Int): Int {
    if (a != null) {
        return a
    } else {
        return b
    }
}

```

The other thing to keep in mind is that an Elvis is like an `if`, in that whatever code is _after_ the Elvis is ONLY run if the thing _before_ the Elvis is null. Again, an example.

```kotlin
fun getValue(value: Int): Int {
    println("Returning value: $value")
    return value
}

fun aOrB(a: Int, b: Int): Int {
    if (getValue(a) > 0 || getValue(b) < 0) {
        return a
    } else {
        return b
    }
}

```

```kotlin
fun getValue(value: Int): Int {
    println("Returning value: $value")
    return value
}

fun aOrB(a: Int?, b: Int): Int {
    return getValue(a) ?: getValue(b)
}

```

In that first example, if `a` was 0, then it would print out “Returning value 0”, and “Returning value 5”. (Assuming `b` is 5) In the second example, if `a` is null, it would print out “Returning value null”, and “Returning value 5”. (Assuming `b` is 5) However, if in the first example, `a` is 1, it would print out “Returning value 1”, and nothing else. In the second example, if `a` is 1, it would print out “Returning value 1”, and nothing else.

Now, the final thing to know is that in the provided example, it’s using that behaviour of evaluating the code _after_ the Elvis IF the code _before_ the Elvis is null.

```kotlin
	fun doX() {
		prop?.also { p ->
			p.print()
		} ?: {
			println("prop is null")
			println("second line")
		}
	}

```

In this case, the Elvis expression is evaluated to return a value. Assuming `prop` is not null, the `also` function is called with a lambda. The `also` function runs, and then returns `prop`. If `prop` _is_ null, then the code _after_ the Elvis is run, which in this case, creates a lambda. That created lambda is then returned.

However, the returned value isn’t being used. It’s not being returned from the method, and it’s not being assigned to a variable. This is why this code works; if you were to try and assign it to a variable, the variable’s type would have to be `Any`, because the return could either be `A`, or `() -> Unit`.

It’s basically the same as if you were to write this code:

```kotlin
fun doX() {
    if ((prop != null && { prop!!.print(); true }.invoke()) || { println("prop is null"); println("second line) }) {
    }
}

```
