But I think Kotlin is much more natural…
# announcements
w
But I think Kotlin is much more natural…
r
a?.b?.toString()?.length
is more natural? even if compiler knows b can not be null?
k
That's not the Kotlin equivalent...
e
Well everything
?.
return is nullable, so the compiler will always be unsure about it is null or not
w
Yep, because of operator associativity
r
okay, so put
?.
everywhere is just like to put if not null everywhere in java
e
Basically yes
Cause the compiler is just doing similar thing under the hood
r
why then we need dot
.
operator ? just use
?.
everywhere
m
because you might not want to silently swallow every null
e
a.b
is for Non-null types, which you're telling the compiler
a
will never be null
m
there are scenarios where certain fields are not supposed to be null, and if that happens it is desirable to let an exception happen, hence
.
and
!!
r
a?.b?.toString()?.length
in this chain b for sure is not null so why to put
?.
?
e
No,
b
is not for sure not null
k
(a?.b)
can be though.
And that's what the next
?.
has to work on.
e
No..they are the same
Everything return by
?.
will be nullable
k
(I think he's talking in the context of something like
data class A(val b: Int)
)
Where
a.b
is never null.
e
That's not how the compiler works, just think how
a?.b
will be translated by the compiler
r
data class A(val b: Int)
this mean b for sure can not be null or not?
k
It can't be null.
a.b
is never null,
a?.b
is null if a was null.
r
than what sens is to put
?.
after it?
k
Because the second
?.
really comes after
(a?.b)
which can be null.
m
val c = a?.b
what’s the value of
c
?
either
Int
or
null
, do you agree?
e
Because the compiler have no idea at runtime
a
will be null or not, so the result of
a?.b
is also not sure at compile time
m
given
c
could be either one of those, then it’s type can only be
Int?
, as a result operating on
c
requires a null check, the safe call operator, or the double bangs (
!!
)
👍 1
r
yes, i understand how it works, but usually you do not need this behaviour, usually you want to stop at first null
k
You want expressions to have this kind of symmetry though.
I'm not sure what the right term is.
But you want a variable like
c
in @menegatti's example to be trivally inlinable.
Without other stuff in the same statement effecting it.
m
@rrader you surely want to stop on the first null, but I don’t get why is
a?.b?.c
getting in your way
you would like the compiler to infer that since
b
is not nullable if
a
is also non-null it can cast it to
Int
instead of keeping it as an
Int
?
r
a?.b?.c
if a is null the chain will continue, so no stop at first null
yes, to infer that it is Int
m
the chain doesn’t in fact continue
r
if b and c are functions, than will continue
m
if you take a look at the generated code for
a?.b?c
, it is:
Copy code
if (a != null) {
    B b = a.getB();
    if (b != null) {
        C c = b.getC(); 
    }
}
so if
a
is null, the rest of the chain is never called, unless the function you’re calling has an extension to
Any?
r
Copy code
class A(val b: Int)

fun main(args: Array<String>) {
    val b : Int? = null
    val a = if (b != null) { A(b) } else { null }
    println(a?.b.toString().length)
    
}
prints 4
m
but then the problem is not the chain per-se, it’s the fact that
toString()
works with nullable types
r
well, you can declare any function on null
this is second thing what I do not understand use cases for
m
as someone pointed out, there are other ways to achieve what you’re trying to do… I can think of at least 2
Copy code
1.
if (a != null) {
    println(a.b.toString().length()
} else {
    // not sure
}

2.
println(a?.let { it.b.toString().length} ?: //not sure )
e
Using
toString()
in this conversation is not really helpful as it has hidden logic inside to deal with
null
m
you don’t define a function on null, but on nullable types
and have a special case, when receiving null
@edwardwongtl true, two different issues are being merged into one. The chain of nullability and extensions on nullable types