4 ms·
* val input: String is a non nullable String. You can never assign null to it, and null will never be assigned to it (unless you do some reflection stupidity, o
by ohgodplsno 5y ago
* val input: String is a non nullable String. You can never assign null to it, and null will never be assigned to it (unless you do some reflection stupidity, or really, really rare cases of you're-fucked-anyways-if-that-happens-something-is-really-wrong)
* val input: String? is a nullable String. It's basically String|null.
There's a third option, which is String!, platform types: since Kotlin has interop with Java, Kotlin will err on trying to be practical for you when calling Java code: it will (rightly so) assume that it is a non-nullable String, but still warn you that it doesn't have the necessary info to infer nullability/non-nullability, so it could technically be null. It's up to you to decide if you want to null-check it. This can be solved in two ways:
- Update your java code to include @Nullable/@NonNull annotations. You should already be doing that anyways, especially if you have control over it.
- Don't call Java code/wrap it in Kotlin wrappers. Kotlin code does not have this type inference issue.
- zeckalpha 5y agoYou just described an implementation of Option types, albeit one with syntactic sugar of a ? Rather than Option<String>.
- kevinmgranger 5y agoThere is no way to have the equivalent of an Option<Option<String>>, so it's not quite the same. That said, if one ever finds themselves seriously using a nested Option, it's probably time to write a new enum for that use case.
- ohgodplsno 5y agoNot necessarily. Not only is it Option.Some/None/ProbablySomeBuyMaybeNoneBecauseJava, it doesn't offer the exact separation that Options can offer: you can stick a value in Option.None (String? can contain null or ""). Nullable types are different to options. (Bonus point for Java that has introduced Option types, that can still be null)
- nemetroid 5y agoThat sounds like an Option type to me: String? :: Option String :: Option.Some null :: Option.None
- Nullabillity 5y agoThe problem with Kotlin is that it only has one global "anything-but-null", so nested ?s are collapsed (String?? is equivalent to String?). This is because it needs to run on the JVM, which only knows about is-null and is-not-null. This interacts terribly with generics, since it means that only one side of the generic boundary can "own" the null value at any one time. To simplify a case where this can cause issues: class Loadable<T>( // null until value is loaded var valueIfLoaded: T?, ) // returns null if user is not found fun getUser(id: String): Loadable<User?> Code that interprets Loadable<T> will get stuck showing a loading bar, since it has no idea about getUser using null for anything else. This doesn't even generate a warning! The "correct thing to do here would be to add a `T: Any` bound on Loadable, which prevents T from itself being a nullable type. That would notify the author of getUser that they need to box the User?, so that the cases are kept separate: data class Box<T>(val value: T) class Loadable<T>( // null until value is loaded var valueIfLoaded: T?, ) // returns null if user is not found fun getUser(id: String): Loadable<Box<T?>> These are things you don't even have to consider when using a typical well-designed Option type (which, mind you, could still have a syntax sugar for T? if you wanted it).
- dtech 5y agoI'd argue that they are fundamentally different. Option is "just another type". You interact with it using constructors, map/flatMap/get etc. You could implement Optional in Java 1.5 but can't implement nullable types in current Java. Nullable types are a feature of the type system and require language support, but the benefit is that you don't touch typical programming patterns val foo: T? = x() if(foo == null) { return ... } // foo is now T, optionality gone v.s. val foo: Option<T> = x() // following must be wrapped and sprinkled in .map, .flatMap, .orElse You can sort-of achieve the first with .isPresent() + .get(), but it clutters the scope, is more verbose, and is not really idiomatic.
- nemetroid 5y ago> not really idiomatic. Really? I haven't used Java in a long time, but in the languages where I've used Optional types, you'd always check for presence once and then extract the value before further use.
- tel 5y agoI don't know Kotlin, but these usually are distinct from Options in an important way, idempotency `String?? = String?` or `String|null|null = String|null`. This equation makes sense for some mental models, but isn't quite the same as Option. In particular, Option[T] has the nice property that you can map over its inner type in a naive fashion `forall S. (T -> S) -> (Option[T] -> Option[S])` whereas the coalescing version above needs an additional assumption that `S` is non-nullable. forall S not null. (T -> S) -> (T? -> S?) This can really get in the way of some kinds of generic programming.
- Semaphor 5y agoThis is pretty much exactly how it works in C# nowadays (though it’s opt-in).