# Elvis operator (?:) always returns the left operand (.toString())

**URL:** <https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681>\
**Category:** Language Design\
**Created:** [April 13, 2023, 8:08am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681 "2023-04-13T08:08:32Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![webber.steven](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/webber.steven/32/10318_2.png) [@webber.steven](https://discuss.kotlinlang.org/u/webber.steven)\
**Post date:** [April 13, 2023, 8:08am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/1 "2023-04-13T08:08:32Z")

</div>

Given the following code :

```auto
val statusCode: String = result?.httpStatusCode?.statusCode.toString()
            ?: Response.Status.NO_CONTENT.statusCode.toString()

```

Why do I get the error :  
Elvis operator (?🙂 always returns the left operand of non-nullable type String

If I understand the “?” correctly, **result** could be null or **httpStatusCode** could be null and therefore the toString function could never be called, requiring the right side of the operator?

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [April 13, 2023, 8:28am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/2 "2023-04-13T08:28:47Z")

</div>

What is the type of `result` variable and `httpStatusCode`, `statusCode` members? It looks they are not nullable.

---

<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:** [April 13, 2023, 9:18am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/3 "2023-04-13T09:18:13Z")

</div>

`toString()` is defined for null types so that it returns a non-nullable `String`. What you need to do is add another ?. after status code like so:

```auto
result?.httpStatusCode?.statusCode?.toString()
            ?: Response.Status.NO_CONTENT.statusCode.toString()

```

Although, I would suggest you do this instead:

```auto
(result?.httpStatusCode ?: Response.Status.NO_CONTENT).statusCode.toString()
```

---

<div class="post-metadata">

**Author:** ![webber.steven](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/webber.steven/32/10318_2.png) [@webber.steven](https://discuss.kotlinlang.org/u/webber.steven)\
**Post date:** [April 13, 2023, 10:42am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/4 "2023-04-13T10:42:50Z")

</div>

Hi.

result is defined as` result: ErrorCodes?`  
httpStatusCode as `val httpStatusCode: Response.Status`,

Thanks for the solution, that looks like a great way to do it.

What I’m struggling with is why the toString function would be called if `result` is null. I know toString works with a null receiver, but my understanding of the ? was that it implemented a null check. If it does perform a null check, why would toString ever be invoked?

---

<div class="post-metadata">

**Author:** ![gidds](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/gidds/32/10865_2.png) [@gidds](https://discuss.kotlinlang.org/u/gidds)\
**Post date:** [April 13, 2023, 6:55pm UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/5 "2023-04-13T18:55:33Z")

</div>

> [@webber.steven](#):
>
> my understanding of the ? was that it implemented a null check.

`?` is not an operator; the operator here is ‘`?.`’. It’s called the safe-call operator: if its LHS is non-null, it calls the RHS function/property, and returns that; otherwise, it returns null.

> [@webber.steven](#):
>
> If it does perform a null check, why would toString ever be invoked?

In your code, note that the last operator is ‘`.`’, not ‘`?.`’:

```
result?.httpStatusCode?.statusCode.toString()

```

To clarify the operator precedence, that means the same as:

```
(result?.httpStatusCode?.statusCode).toString()

```

The `(…)` expression may evaluate to null (if `result` is null, or its `httpStatusCode` is null, or if _its_ `statusCode` is null), or to a non-null value — but either way, `toString()` will be called on the result. And since `toString()` returns a non-nullable String, then the whole expression never evaluates to null.

---

<div class="post-metadata">

**Author:** ![webber.steven](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/webber.steven/32/10318_2.png) [@webber.steven](https://discuss.kotlinlang.org/u/webber.steven)\
**Post date:** [April 14, 2023, 8:42am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/6 "2023-04-14T08:42:40Z")

</div>

Thank you. That clarifies the why nicely.

I think I’m missing something fundamental about how these operators work. My expectation is that toString is a method/function on the Int object and as such would be called (or not) based purely on whether I reach that point. (The Int object)

So result?. returns a null and the operation stops there. I would not have expected the evaluation to continue to httpStatusCode and then again to statusCode.

In Java I would have received a null pointer exception at result.getHttpStatusCode(). It would never have evaluated the next value.

If I’m understanding the above correctly though, the safe call operator does not stop the operation, it just returns a null.

So we’d have result?. evaluating to null and then (get)httpStatusCode would be called on that null value (and that’s why I needed the safe call operator at that point because even though it’s not a nullable variable, it is nullable now because of the previous ?.)

Then (get)statusCode would be called on httpStatusCode null value returned by the safe operator.

Then toString is called on the result and the reason I don’t need a forced ?. on that is because toString excepts a null receiver…?

If that is how it’s working, what would be the result of this call?

result?.httpStatusCode?.statusCode?.let { toString() } // Is let still called on the null?

Also, why does this return a different value? (If I use the null safe operator on the last variable/statusCode)

result?.httpStatusCode?.statusCode?.toString() // Why does this not invoke toString with a null and therefore return an empty string

---

<div class="post-metadata">

**Author:** ![gidds](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/gidds/32/10865_2.png) [@gidds](https://discuss.kotlinlang.org/u/gidds)\
**Post date:** [April 14, 2023, 9:58am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/7 "2023-04-14T09:58:25Z")

</div>

> [@webber.steven](#):
>
> My expectation is that toString is a method/function on the Int object

Yes, but that’s not the `toString()` that’s being called here…

The top-level class `Any` has a [`toString()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/to-string.html) method, so every object can be converted to a string. Every other class can override that method (and it’s often a good idea to do so). So yes, `Int` has a [`toString()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/to-string.html) that converts the number to a string in the usual way.

However, there’s _also_ a built-in top-level extension function: [fun `Any?.toString()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/to-string.html). An [extension function](https://kotlinlang.org/docs/extensions.html#extension-functions) is a method that’s defined _outside_ of a class, but has some syntactic sugar so calls to it _look_ like calling a method of the class.

Note that in this case it’s an extension on `Any?`, which is nullable — and so (unlike normal methods), it can be called on a null. (The implementation for that function isn’t public, but the effect is simple: it returns `"null"` when called on a null, else it calls the object’s own `toString()` method. On Kotlin/JVM, it may translate to [`java.lang.String.valueOf(Object)`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#valueOf-java.lang.Object-), which does that.)

Because your code is calling `toString()` on a nullable value, the extension function is the only possible `toString()` you could be calling, and so that’s what the compiler selects.

When you change the last operator to a safe-call ‘`?.`’, then the compiler knows that you’re calling it on a non-null object, and so it selects the more specific [`Any.toString()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/to-string.html) method instead.

(These are all standard language features — though nullable receivers aren’t common, and this is probably the first one many people see.)

If you’re using an IDE such as IntelliJ, it can often help you see what’s going on in cases such as this: try hovering over or right-clicking or Cmd+tapping an operator or function call to see which function is actually being called.

---

<div class="post-metadata">

**Author:** ![ebrowne72](https://avatars.discourse-cdn.com/v4/letter/e/85f322/32.png) [@ebrowne72](https://discuss.kotlinlang.org/u/ebrowne72)\
**Post date:** [April 14, 2023, 10:34pm UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/8 "2023-04-14T22:34:01Z")

</div>

Here is what’s happening when `result?.httpStatusCode?.statusCode.toString()` is evaluated:

- First Kotlin evaluates `result?.httpStatusCode`. It looks at the left side and sees `result` is `null`, so this evaluates to `null`.
- Then it evaluates the next part of the statement, which is now `null?.statusCode`. Once again the left side is `null`, so this evaluates to `null`.
- The next part of the statement is now `null.toString()`, so Kotlin calls the `Any?.toString()` extension function witch returns a string.

---

<div class="post-metadata">

**Author:** ![raphael.tarita](https://avatars.discourse-cdn.com/v4/letter/r/3ab097/32.png) [@raphael.tarita](https://discuss.kotlinlang.org/u/raphael.tarita)\
**Post date:** [April 21, 2023, 7:44am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/9 "2023-04-21T07:44:10Z")

</div>

> [@webber.steven](#):
>
> So result?. returns a null and the operation stops there. I would not have expected the evaluation to continue to httpStatusCode and then again to statusCode.
> 
> In Java I would have received a null pointer exception at result.getHttpStatusCode(). It would never have evaluated the next value.
> 
> If I’m understanding the above correctly though, the safe call operator does not stop the operation, it just returns a null.

I feel like this hasn’t been properly answered yet in this thread. With your last remark, you are correct. The safe call (`?.`) is not short-circuiting anything, it’s a binary operator with a clear definition of what it returns for which operands. The left operand can be any nullable value and the right operand is a member expression for the type of that value. Safe call is defined as:

- if the left operand is not null, the result of the expression is the result of the member expression on the right
- if the left operand is null, the result of the expression is `null`

At no point is the execution “stopped” early or anything, it’s just skipping the member expression and returning `null`.

The key here is the term “expression”, because it means that it has to return a value. `?.` can be used in expressions (and not just in statements), therefore it needs to return a value in every possible case.

---

<div class="post-metadata">

**Author:** ![gidds](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/gidds/32/10865_2.png) [@gidds](https://discuss.kotlinlang.org/u/gidds)\
**Post date:** [April 21, 2023, 11:28am UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/10 "2023-04-21T11:28:56Z")

</div>

> [@raphael.tarita](#):
>
> The safe call (`?.`) is not short-circuiting anything

As you say, the operator evaluates its right-hand side only if the left-hand side evaluates to non-null; it does _not_ evaluate its right-hand side otherwise.

This behaviour _is_ an example of what’s usually called [short-circuit evaluation](https://en.wikipedia.org/wiki/Short-circuit_evaluation), in exactly the same way as the `&&` and `||` operators in Kotlin (and many other languages). The official Kotlin docs make this explicit; the reference for the [`and`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/and.html) function says that:

> Unlike the `&&` operator, this function does not perform short-circuit evaluation.

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [April 21, 2023, 12:48pm UTC](https://discuss.kotlinlang.org/t/elvis-operator-always-returns-the-left-operand-tostring/26681/11 "2023-04-21T12:48:14Z")

</div>

An alternative way of writting `subject?.function()` would be something like `optional.letNotNull { it.function() }` or maybe `subject.onNotNull {...}`

I get a feeling that the confusion revolves around chaining the calls? Here’s what that would look like using our `letNotNull()` function:

```run-kotlin
fun <T, R> T?.letNotNull(block: (T) -> R): R? {
  return if (this != null) block(this) else null
}
fun <T, R> T?.letNull(block: (T?) -> R): R? {
  return if (this == null) block(this) else this
}

val result = 5
val Any.httpStatusCode get() = 5
val Any.statusCode get() = 5
object Response {
    object Status {
      val NO_CONTENT = 5
    }
}
fun main() {
//sampleStart
// OP's original sample
/*
result?.httpStatusCode?.statusCode.toString()
    ?: Response.Status.NO_CONTENT.statusCode.toString()
*/
result // Could return null or HttpResponse
    .letNotNull { it.httpStatusCode } // Could return null or HttpStatusCode
    .letNotNull { it.statusCode } // Could return null or StatusCode
    .toString() // Can only return String
    .letNull { Response.Status.NO_CONTENT.statusCode.toString() }

// kyay10's fixed sample
/*
result?.httpStatusCode?.statusCode?.toString()
    ?: Response.Status.NO_CONTENT.statusCode.toString()
*/
result // Could return null or HttpResponse
    .letNotNull { it.httpStatusCode } // Could return null or HttpStatusCode
    .letNotNull { it.statusCode } // Could return null or StatusCode
    .letNotNull { it.toString() } // Could return null or StatusCode
    .letNull { Response.Status.NO_CONTENT.statusCode.toString() }
//sampleEnd
}

```
