https://kotlinlang.org logo
m

Michael Böiers

04/30/2021, 12:46 PM
I’m wondering why the if statement doesn’t expect a nullable Boolean type. What would be the disadvantage of allowing it? Consider this:
Copy code
if (foo?.isNotEmpty() ?: false) { … }
That works, but it’s not really concise. Wouldn’t it be better (and safe) if we could just write
Copy code
if (foo?.isNotEmpty()) { … }
👍 1
🚫 3
s

Stephan Schroeder

04/30/2021, 12:53 PM
how is autocasting
null
to
false
safer and better? (and if you have an answer, you won't find many (relatively spoken) who aggree with you in this chat.)
👍 2
c

christophsturm

04/30/2021, 12:54 PM
in your example:
if (!foo.isNullOrEmpty()) {}
m

Michael Böiers

04/30/2021, 12:57 PM
@christophsturm Yes, that works well for Strings, but not so much for generic conditions. I suppose I could always write my own extension function to hide away the elvis operator. 🙂
(Just like isNullOrEmpty does)
c

christophsturm

04/30/2021, 12:57 PM
in the end you don’t want to arrive in a situation where a flag is either null or false or true.
m

Michael Böiers

04/30/2021, 12:58 PM
That’s where I am sometimes. The best solution is of course to avoid the nullable type in the first place.
c

christophsturm

04/30/2021, 1:01 PM
i think one of the most common usecases are optional strings and there isNullOrEmpty helps.
and for optional boolean values you will probably assign a default value with the elvis operator at first use
m

Michael Böiers

04/30/2021, 1:09 PM
Ok, it was a bad idea. Blame it on Friday! 🙂
r

Roukanken

04/30/2021, 1:20 PM
optional booleans are almost never a good idea non-optional booleans with default value replace them in 90% of cases at least and if someone says "But I need 3 diff values!" then it's not a fucking boolean then! Get an enum or your some of own class instead. Sadly I see this often in production code, with comments like
false means A happened, true means B happened, null means OK
Anyways, enum or replacing with default value at earliest possibility / handling it somehow else (example sometimes return from function can be a solution).
💯 1
also if you need to check smth on a nullable variable sometimes
if(foo != null && foo.isNotEmpty())
might be more readable than default value. Ofc, only works on local variables/args...
m

Michael Böiers

04/30/2021, 1:25 PM
Yes, that’s kind of the “java way” of doing it. Works well for short variable names, otherwise the expression gets kind of lengthy. In that case I’d rather go elvis 🙂
r

Roukanken

04/30/2021, 1:25 PM
yeah, it depends on the expresion, that's why "sometimes"
but if the expression is long enough, I would just assign the boolean result to variable (so it can get name)
m

Michael Böiers

04/30/2021, 1:26 PM
Now I’m wondering why the isNotEmpty function doesn’t accept a null receiver. I guess it’s because these things are meant to be made explicit in Kotlin
Perhaps something like
CharSequence?.isNeitherNullNorEmpty()
would be nice - it’s verbose, but it seems to be the Kotlin way.
👍 1
It would be nice to have smart casting support when using these functions, at least if they’re inline.
r

Roukanken

04/30/2021, 1:29 PM
(that's what contracts are for no?)
n

Nir

04/30/2021, 1:31 PM
You could have an extension for booleans themselves
Instead of trying to add an extension for every specific case
r

Roukanken

04/30/2021, 1:32 PM
Copy code
@OptIn(ExperimentalContracts::class)
fun CharSequence?.isNotNullOrEmpty(): Boolean {
    contract { 
        returns(true) implies (this@isNotNullOrEmpty != null)
    }
    
    return this != null && this.isNotEmpty()
}

fun bar(foo: String?) =
    if (foo.isNotNullOrEmpty()) foo + "bar" else null
this works
ah wait, plus is nullabe, smth else
m

Michael Böiers

04/30/2021, 1:33 PM
Haven’t looked into contracts yet … interesting!
n

Nir

04/30/2021, 1:33 PM
Then you could write foo?.isBar().isTrue()
r

Roukanken

04/30/2021, 1:33 PM
anyways, smth like that should work, I'm not too knowledgable of them either 😛
n

Nir

04/30/2021, 1:33 PM
Or if you want to be more explicit, isTrueAndNotNull
But I think isTrue is good enough given the type signature
But maybe that's not enough improvement over ?: false
m

Michael Böiers

04/30/2021, 1:35 PM
Contract works in this case, but it’s experimental …
i

ilya.gorbunov

04/30/2021, 2:05 PM
Is
.isTrue()
significantly better than
== true
?
e

ephemient

04/30/2021, 2:09 PM
yeah I was going to say, I thought Kotlin style was
== true
over
?: false
n

Nir

04/30/2021, 2:09 PM
Ah right, I actually forgot that == works on nullables
kind of silly
c

christophsturm

04/30/2021, 2:10 PM
nice! i always thought
== true
is a noop but thats only true for non nullable booleans
n

Nir

04/30/2021, 2:11 PM
I think, to be honest, you could make an argument that if something works with == true, it should just work directly as the condition
1
I wouldn't really consider this "truthiness" or "autocasting", IMHO
r

Roukanken

04/30/2021, 2:12 PM
yes you could, but I still think you should get kicked in face by your IDE, "Care this is nullable!" and whenever to handle it with
?:
or
==
it's whatever, but it should be explicit
n

Nir

04/30/2021, 2:14 PM
I dunno,
== true
is not terribly explicit to me
when I look at
if (<expression>)
and
if (<expression> == true)
I'd expect them to be the same
e

ephemient

04/30/2021, 2:15 PM
is
== true
or
!= false
the right choice? they have different behavior on null
o

okarm

04/30/2021, 2:15 PM
It is explicit (when compared to ?: false), because you're explicitly specifying the value you are interested in.
n

Nir

04/30/2021, 2:15 PM
but
if
already does that
the value you're interested in is
true
e

ephemient

04/30/2021, 2:16 PM
is it?
in many languages it's just looking for a "truthy" thing
n

Nir

04/30/2021, 2:17 PM
truthiness would make the range of acceptable things in
if
broader
in python there are things that you can't
== True
(or maybe you can but they return False)
But they will "count" as True inside an if
What we're talking about here is that Kotlin's if is actually even narrower than
== true
e

ephemient

04/30/2021, 2:18 PM
== true
in C, Perl, Python, Ruby, JS etc. changes what an
if
will do
r

Roukanken

04/30/2021, 2:18 PM
(that's true here too, tho)
e

ephemient

04/30/2021, 2:18 PM
it doesn't in Java and Kotlin, because they require a strict boolean
n

Nir

04/30/2021, 2:19 PM
It does, because == true can make something compile
that didn't
as we have just seen 🙂
e

ephemient

04/30/2021, 2:19 PM
not compiling doesn't change behavior, there was none before
n

Nir

04/30/2021, 2:19 PM
different definitions of change behavior
r

Roukanken

04/30/2021, 2:20 PM
imho, going from "no behavior" to "some" is a change
e

ephemient

04/30/2021, 2:20 PM
do I need to explicitly say, changes runtime behavior?
n

Nir

04/30/2021, 2:20 PM
Do I need to say, explicitly changes program behavior?
e

ephemient

04/30/2021, 2:20 PM
what else matters
n

Nir

04/30/2021, 2:20 PM
etc, this is poitnless
Anyway, the point is that it's pretty unusual for an if not to compile with an expression, but to compile with == true. You can force it to happen in languages that allow overloading operator==, but it would be considered a crazy thing to do
1
Actually, interestingly Swift does exactly the same thing 🙂 So perhaps, not that unusual in the context of languages with nullable types
o

okarm

04/30/2021, 2:27 PM
That's like saying "It's unusual
if(Char)
doesn't compile but `if(Char == 'a')`", no? With nullable Boolean you're no longer dealing with "standard bool", but you're comparing two values that might as well be random.
n

Nir

04/30/2021, 2:27 PM
It's not like that example at all, no, because the value on the right is not
true
I guess what it boils down to, which is pretty unique to languages with null baked into the type system, is that there's a type above boolean
o

okarm

04/30/2021, 2:31 PM
But with null in the mix "the value on the right is not `true`" no longer makes sense
You're testing if something is exactly
true
- but please forget about the special treatment of primitive boolean. It's been lifted, promoted to a 3-way value. In that sense it's no different from any other
equals
comparison.
m

Michael Böiers

04/30/2021, 2:35 PM
@Nir consider that == is different from === in Kotlin.
n

Nir

04/30/2021, 2:46 PM
@okarm I'm not sure what you mean by that
o

okarm

04/30/2021, 2:47 PM
I guess what it boils down to, which is pretty unique to languages with null baked into the type system, is that there's a type above boolean
This
n

Nir

04/30/2021, 2:47 PM
yep
Basically you need some form of implicit conversion in a language for this to work
Either that, or special == between different types
In this case, it's basically the implicit conversion of a type to its supertype (in this case, the nullable version of its own type)
@Michael Böiers that's not really relevant here tbh
m

Michael Böiers

05/01/2021, 9:27 PM
@Nir No, it’s not. Nevermind. 🙂
🙂 1
2 Views