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-nullbenleggiero
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().fooilya.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 nullRuckus
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 nullRuckus
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 nullRuckus
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 OtherRuckus
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