Mikael Alfredsson
04/13/2020, 5:24 PMdata class B(val i: Int)
data class A(val b: B)
class Test {
var a: A? = A(B(1))
fun get(): Int {
return a?.b.i ?: -1
}
}
the expression a?.b.i
must in kotlin be written as a?.b?.i
but in reality, if a
isnt null, we know that b
must contain i
(in Swift i think the former expression is valid)rbares
04/13/2020, 5:44 PM.
denoting normal access and ?.
denoting a safe call (i.e. give me the right hand side if the left hand side is non-null, and null otherwise). If a
was null then a?.b.i
would be equivalent to null.i
which will always fail, whereas a?.b?.i
would be equivalent to null?.i
which then successfully collapses down to null
.
Swift is very similar, with
https://docs.swift.org/swift-book/LanguageGuide/OptionalChaining.html giving an example of john.residence?.address?.street
. There is a nice list of examples for various languages on wiki https://en.wikipedia.org/wiki/Safe_navigation_operatorrbares
04/13/2020, 5:58 PM?.
is left-associative. So a?.b?.c
is (a?.b)?.c
Mikael Alfredsson
04/13/2020, 6:12 PMMikael Alfredsson
04/13/2020, 6:16 PMstruct B {var i: Int}
struct A {var b: B}
class Test {
var a: A? = A(b:B(i:1))
func get() -> Int {
return a?.b.i ?? -1
}
}
Mikael Alfredsson
04/13/2020, 6:16 PMb
and i
rbares
04/13/2020, 6:41 PMhallvard
04/14/2020, 6:33 AMIf a was null then a?.b.i would be equivalent to null.i
hallvard
04/14/2020, 6:34 AMnull
, then the statement should return already at that point, so there should be no null.B.i
. I must agree with OP here, that demanding a safe call on B in this case seems odd.Mikael Alfredsson
04/14/2020, 6:35 AMif a==null return -1 else return a.b.i
since if a isnt null, it will always contain b
and b will always contain c
(sorry, missed your last post)Mikael Alfredsson
04/14/2020, 6:36 AMrbares
04/14/2020, 7:57 AMa?.b?.i
, so doesn't suggest a shortcut. See also https://kotlin.github.io/kotlin-spec/#navigation-operators which suggests it is left-associative and does not suggest a shortcut.hallvard
04/14/2020, 8:43 AMhallvard
04/14/2020, 8:45 AMa?.b?.i
, where does the null come from if a
is null? It's not very logical to imagine that it comes from the b?.
part, as already a?.
is null. So that's the firs and most obvious reason for my believing so. And also the reasoning behind the original quastion, if I am not mistaken.Mikael Alfredsson
04/14/2020, 8:47 AMa
is null it will jump to return -1
after that it could just get b
and i
but it gets b
and performs another nullcheck.Mikael Alfredsson
04/14/2020, 8:48 AMpublic final get()I
L0
LINENUMBER 22 L0
ALOAD 0
GETFIELD tst/Test.a : Ltst/A;
DUP
IFNULL L1
INVOKEVIRTUAL tst/A.getB ()Ltst/B; <-- getB is marked as non null so no need to test for null here
DUP
IFNULL L1
INVOKEVIRTUAL tst/B.getI ()I
GOTO L2
L1
LINENUMBER 22 L1
POP
ICONST_M1
L2
IRETURN
L3
LOCALVARIABLE this Ltst/Test; L0 L3 0
MAXSTACK = 2
MAXLOCALS = 1
hallvard
04/14/2020, 8:54 AMval B
inside A
. Interresting, but too time-consuming for me now. I think oyu should raise an issue for this on the JB issue tracker, maybe we'll get a nice explanation. Thanks for the chat!