|
|
|
|
|
by mraleph
832 days ago
|
|
The reason why languages promote variable types based on control flow is because developers en masse actually expect that to happen, e.g. facing the code like Dog? maybeDog;
if (maybeDog != null) {
maybeDog.bark();
}
If compiler says "sorry, maybeDog might be null", developer (rightfully so) usually responds "but I have just checked and I know it is not, why do you bother me?". So languages chose to accommodate this.> What if I want to set the value back to nil if it is not-nil? You can. The type of the variable does not actually change. You could say that the information about more precise type is simply propagated to the uses which are guarded by the control flow. The following will compile just fine: Dog? maybeDog;
if (maybeDog != null) {
maybeDog.bark();
maybeDog = null;
}
> Why should I have to wrap things back in an optional if I want to pass it along as such?You don't, with a few exceptions. There is a subtype relationship between T and T?: T <: T?, so the following is just fine: void foo(Dog? maybeDog);
Dog? maybeDog;
if (maybeDog != null) {
maybeDog.bark();
foo(maybeDog); // Dog can be used where Dog? is expected
}
You might need to account for it in places where type inference infers type which is too precise, e.g. Dog? maybeDog;
if (maybeDog != null) {
// This will be List<Dog> rather than List<Dog?>.
final listOfDogs = [maybeDog];
}
Though I don't think it is that bad of a problem in practice. |
|
Also, fwiw, I was mostly talking about things like the last example you gave. I guess it would be possible that in circumstances where T is invalid but T? would be valid, the language actually silently undos the refinement to make that code work. However, I am not sure this is actually a positive, and it doesn't help with the ambiguous cases anyways.