kevinmost
01/28/2018, 3:18 AM?
that will be invoked even if the receiver is null
. For example, System.getProperty("os.name")?.toLowerCase().isNullOrEmpty()
, and a distinction must be made if you want that function to execute no matter what, or only when the receiver is non-null
benleggiero
01/28/2018, 5:57 AM.toLowerCase()
will never ever return null
. It’s promised that in its signature with : String
instead of : String?
. We know this at compile-time.
In your example, .isNullOrEmpty()
can be called in my isMac2
and isMac3
examples, too, and the compiler also warns that this is silly, with a warning saying “Call on not-null type may be reduced”ilya.gorbunov
01/28/2018, 6:12 AMosName?.toLowerCase()
will have null
value if osName
is null
, therefore the type of this expression is String?
benleggiero
01/28/2018, 6:54 AMosName?.toLowerCase().startsWith()
would also have type String?
, but you just wouldn’t be required to type as many `?`s since the compiler knows that if you got far enough to run the first function, you are no longer dealing with `null`s and can safely call the second without using the ?.
operator.Ruckus
01/28/2018, 3:51 PMfun String?.startsWith()
that has a little different functionality?kevinmost
01/28/2018, 4:20 PM?.
between each function call because it makes it explicit that the function is going to be called only if the preceding type is non-null or if it will be called unconditionallybenleggiero
01/29/2018, 3:55 AMnullable?.neverNull()?.foo
to this:
nullable?.neverNull().foo
ilya.gorbunov
01/29/2018, 4:36 AMfoo
is an extension for nullable type (like let
or isNullOrEmpty
) shall it be called in the last example or not?benleggiero
01/29/2018, 4:52 AMnullable?.neverNull().foo
? since neverNull()
is only called if nullable
is not null
, then foo
will also only be called if nullable
is not null. This will stay consistent with the current behavior. I don’t see the confusion point here.ilya.gorbunov
01/29/2018, 4:53 AMfoo
is called in any case.Pavlo Liapota
01/29/2018, 8:02 AMfoo
can be extension property declared on nullable type like this:
val String?.foo get() = this ?: "foo"
.
So if nullable
is null
then whole expression will be evaluated to "foo"
.elect
01/29/2018, 9:29 AMnullable
is null
, the code flow should jump at the ?:
If foo
gets called in any case then it's wrong from a logic point of viewRuckus
01/29/2018, 3:47 PMelect
01/29/2018, 4:00 PMnullable?.neverNull().foo
, I'd expect here foo to be callable on not-nullable typeRuckus
01/29/2018, 4:08 PMneverNull()
returns Thing
, then nullable?.neverNull()
returns Thing?
. I could define a val Thing?.foo
that will (and should) always be called. For example:
class Thing(val foo: String)
class Other(val name: String) {
fun neverNull() = Thing(name)
}
val Thing?.foo get() = this?.foo ?: "[bad thing]"
val nullable: Other? = null
println(nullable?.neverNull()?.foo) // prints `null`
println(nullable?.neverNull().foo) // prints `[bad thing]`
Ruckus
01/29/2018, 4:10 PMnull
.elect
01/29/2018, 4:11 PMprintln(nullable?.neverNull().foo)
, if nullable
is null
, I'd expect it to println directly null
Ruckus
01/29/2018, 4:11 PM.foo
call, so ?:
is not always the answer (as it would require many nested (thing.foo ?: default).nextCall()
Ruckus
01/29/2018, 4:12 PMThing?.foo
?elect
01/29/2018, 4:13 PMa()?.b()?.c()
, the very first step returning a null
should automatically make the code flow jump at the ?:
if any, otherwise simply returns null
Ruckus
01/29/2018, 4:14 PMAny?.toString()
elect
01/29/2018, 4:16 PMelect
01/29/2018, 4:17 PMprintln(nullable?.neverNull().foo)
, if nullable
is null
and there is no ?:
, I expect to read null
in console.elect
01/29/2018, 4:19 PMneverNull()
cannot produce a nullable output, that's why there should be no additional ?
elect
01/29/2018, 4:19 PMneverNull()
will be executed only if nullable != null
...elect
01/29/2018, 4:20 PMRuckus
01/29/2018, 4:47 PM.neverNull()
cannot produce a null, but ?.neverNull()
can.elect
01/29/2018, 4:49 PMnull
, I'd expect the code flow to skip any further call, that is .neverNull()
, and jump directly to ?:
if any, or returns directly null
Ruckus
01/29/2018, 4:50 PMelect
01/29/2018, 4:52 PM?.
as "go on only if not null"elect
01/29/2018, 4:53 PM?
Ruckus
01/29/2018, 4:53 PM?.
means.Ruckus
01/29/2018, 4:54 PMelect
01/29/2018, 4:56 PMb?.length
returns b.length
if b
is not null
, and null
otherwise.Ruckus
01/29/2018, 4:57 PMelect
01/29/2018, 4:58 PMRuckus
01/29/2018, 4:59 PMelect
01/29/2018, 4:59 PMRuckus
01/29/2018, 4:59 PMRuckus
01/29/2018, 5:00 PMThing?.foo
was a pretty good example of that, also the standard library Any?.toString()
ilya.gorbunov
01/29/2018, 5:10 PMelect
01/29/2018, 5:11 PMclass Wrapper
instead class Other
Ruckus
01/29/2018, 5:16 PMbenleggiero
01/29/2018, 6:11 PMfoo
was declared as an extension funciton on an optional type, one could just use the ever-disambiguating parentheses (that should always be used when writing confusing/niche syntax) like this: (nullable?.neverNull()).foo
. Simple, self-explanatory, and easy for maintainers/newcomers to understand what's going on!
Additional examples:
(nullable?.neverNull()).toString()
would return "null"
(current behavior), whereas nullable?.neverNull().toString()
would return null
. (just like today's nullable?.neverNull()?.toString()
)
(nullable?.neverNull()).let { ... }
would call let
where it
is null
(current behavior), whereas nullable?.neverNull().let { ... }
would never have its let
block called at all. (just like today's nullable?.neverNull()?.let { ... }
)benleggiero
01/29/2018, 6:12 PM?.
operator. It's bizarre and confusing that Kotlin doesn't.Ruckus
01/29/2018, 6:42 PM(nullable?.neverNull()).foo
and nullable?.neverNull().foo
return different values is mind boggling.
I don't know about Swift and C#, but in Rust the short circuit is quite a bit different. It does an immediate return from the current function with an error result, not just a skip to the end of the line, so it's not so much a short circuit as an early return.ilya.gorbunov
01/29/2018, 6:45 PM.foo()
is called always and ?.foo()
is called only if receiver is not null. No matter where it is in a chain of calls.kevinmost
01/29/2018, 8:57 PMbenleggiero
02/01/2018, 1:28 AMkevinmost
02/01/2018, 4:57 AM