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.
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.
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.
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
}
}
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.
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:
fun doX() {
if ((prop != null && { prop!!.print(); true }.invoke()) || { println("prop is null"); println("second line) }) {
}
}