-
Notifications
You must be signed in to change notification settings - Fork 700
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Propose new name for "Null assertion operator" #5252
Comments
Thanks so much for consolidating all of this information @MaryaBelanger! I'm excited to hear from others and for us to consolidate the terminology. I'll be happy with whatever is chosen, as in the end, I think consistency and familiarity are the most important over definite accuracy. I will specifically call out that for "non-null assertion operator", some familiarity is already there with Typescript and Kotlin using similar terminology. I also want to make sure that it's noted that choosing a name here should likely also apply to the null assert pattern type which has similar semantics. There is also a pre-existing Null check pattern type so we should be careful with that term as well. Thanks everyone for your thoughts! |
|
I agree that this is probably the best of the suggestions. And I don't think it's inconsistent with an assert statement: both check a condition and throw if it isn't One advantage is that the term is used in Kotlin, so there's some familiarity. One disadvantage is that it's used in TypeScript, but has a different semantic (no exception is thrown unless the pointer is dereferenced at some future point).
The concern I have with this is that it isn't used anywhere that I can see. A search doesn't turn up any uses of that phrase, just pages that happen to have those three words in one order or another. I think it would be better to use a phrase that will be familiar to at least some users. |
I'm partial to "throw if null operator" because it is unambiguous. If that option doesn't have much other support I'd be OK with calling it "non-null assertion operator". |
Like "null exception operator", there are zero search hits for that name, suggesting that it would be hard for users to search for it. |
I think the phrase 'non-null assertion operator' is delightfully accurate: The presence of this operator indicates that the author strongly believes that the value of the given expression will not be null, and it seems natural that violations of strongly held beliefs will lead to exceptional events. There is a danger that the word 'assertion' is associated with the The phrase is rather long, though. Perhaps we could say that the non-null assertion operator is also known as the 'bang' operator. If we take care to avoid using 'the bang operator' to denote negation then it's probably OK to reserve that phrase for this operator, and it's certainly a lot shorter. ;-) |
That's why I was trying to think of a new, slightly more compact name. But since it sounds like non-null assertion operator is the best choice, I will make a point of listing synonyms in the glossary definition so if we do want to abbreviate to "bang" or something else, those will be listed with "non-null assertion operator" for reference. Thanks everyone! |
Fwiw the current language spec heavily uses the term "assertion" and qualifications such as "When assertions are not enabled", and these are frequently if not always disconnected from the "assert" function. So we might want to update the language spec there 🤷♂️ . Very few people would actually be reading the spec and get confused, but the terminology is in conflict with the behavior of I still think |
I like the "null-bang" operator, because if the value is null, the program goes "Bang!". It's short and descriptive of the syntax. What's not to like? 😁 I'd accept "null check operator". It's not absolutely precise (it deosn't say whether being The "throw if null operator" is precise and to the point. It's just long. Long isn't good in naming. We should call (And people are still unable to name the If we're trying to name the operation, then that's a different beast. 😉 |
For what it's worth, the language already has a "if-null expression" ( I don't love "non-null assertion" because it suggests they get turned off when asserts are off, but the familiarity argument probably outweighs that. |
Maybe |
Since no one else has chimed on in on that suggestion, I think It's not as searchable yet, but some sort-of relevant results do come up. The one concern is that to quote @eernstg: "there may not exist a type In the end though, I don't think the assertion worry is a big problem either, as whether or not assertions are enabled, I expect them to hold true. There's also the fact that the word "assertion" has been in the common term and propagated for the past few years through the official documentation, it may be hard to fight against anyway. |
Overall, I think having any consistent term (that is still searchable eventually) is better than what we have now, even if it's slightly incorrect. Even if we don't come to a decision on this soon, it seems we should at least update the Since these two seem to be the most likely to be understandable and searchable to Dart programmers from what's been discussed, I'm curious if anyone feels they're not acceptable at all? Otherwise maybe we should just move forward with one, at least on the website, and see how it goes. How about some informal opinions?
|
I'm not fond of 'cast'. While the operator could accurately be thought of as a cast, that isn't now it's presented to the user in the exception that's thrown:
I also suspect that users don't think of it as a cast. (If we settle on a name we should update the analyzer / CFE / VM messages to match.) |
I call it a null check or null check operator but would be happy to start calling it a not-null check. The term check is used in lots of places for things that check something and throw if not satisfied, e.g. I'm not fond of cast, which in some languages is a conversion. |
It may not be how it's presented to the user in error messages, but I think it is like a cast in terms of actual semantics:
The only difference between |
While I understand that the semantics of the operations, from a specification point of view, are the same, I was thinking about the UX presentation. Of course, the UX presentation can be changed, but existing users might be familiar with the current behavior and the current behavior might have influenced their mental model. In attempting to make that argument, I probably should have been more detailed. I used the following to get the exception message for the operator ("Null check operator used on a null value"): void main() {
f(null);
}
void f(int? x) {
x!;
} But if we instead write void main() {
f(null);
}
void f(int? x) {
x as int;
} the exception message is "type 'Null' is not a subtype of type 'int' in type cast". The two exception messages are different enough that users might not think of |
I think you are right about that, but I often find that is actually a mistake: Some developers think of it as a non-problematic operator, that you just add to "please the type system" and don't consider that it can actually fail. I speculate that having a stronger 'cast' connotation will make it much more clear, that it should only be used when you are confident about the type. |
That's true, and it's because that's how it works in TypeScript. But the Kotlin version works the same way as Dart's and is also called the "non-null assertion operator", so Kotlin doesn't call out an association with casts. (Just a data point, not an argument.) |
It's not really a cast, because a cast is to something, and there may be no type to cast to. It's not the same as So, not a cast. It's a throw-if- |
Sorry, I don't undetstand, @lrhn. Can you elaborate please on how it's not a cast? It seems to fail in pretty similar ways (just with a different error message, which we could update): int? i;
int? j;
...
int x = i!;
// Throws Unhandled exception: Null check operator used on a null value
int y = j as int;
// Throws Unhandled exception: type 'Null' is not a subtype of type 'int' in type cast |
A "cast" is, in Dart terminology, a check for whether a value satifies a specific type. Example: num? x = ...;
var y = x as int; // `y` gets type `int`. The cast of the value of Now take: FutureOr<int?> x = ...;
var y = x!; Which type is It's not One could argue that it's cast to the intersection type There is no type The So is it a "null-throw-guard"? Maybe just "null-throw operator"? Feels ambiguous, so "throw-if-null operator" is better. (A cast is a "type guard", it prevents bad types from getting past. A |
I'm going to put my DevRel hat on and suggest that technical accuracy is less important than how easy it is to communicate between developers. I'd argue that leaning too heavily on technicality and naming it something like It might have been a facetious suggestion, but I actually vote for this:
For these reasons:
Also, it's much easier and more fun to write null-bang. Who will think of the docs writers and content creators! 🙃 |
I agree that accuracy isn't super essential here and communication between developers is super important, but also understanding something from the name is too and helps enable communication. I feel a name such as "null bang" wouldn't be understood in discussion by a developer unfamiliar with the name. I'd argue it actually adds work for beginners, since it's a separate concept to learn, while |
Completely generally, I prefer "not-null" to "non-null" for what this operator does. Maybe because "non-null" sounds like an adjective, but it's about the value, not the next word. A "non-null assert" is not an assert which is non-null? Calling suffix- Using "not null check" sounds more like it returns a (Still like "null-bang!", but it's true that it has no associations to help it being understood.) |
Background
@dart-lang/language-team @bwilkerson I would like to settle on a term for "Null assertion operator"/
!
and then update all of our resources (docs, lints, diagnostics, in the SDK, etc) to use that term exclusively as part of the effort to make Dart's terminology more consistent (#5247).There's been a lot of discussion going on (dart-lang/linter#3008 , dart-lang/sdk#47185) but it doesn't feel conclusive enough yet to make a decision. Summarizing the major points:
null assertion operator
(currently standard on dart.dev)non-null assertion operator
null check operator
/non-null check operator
... != null
,as
, etc.).non-null enforcing
,non-null cast
,null failure
,throw if null
,unwrap
(Swift), etc are floating around too.(@parlough's longer summary of options)
Proposal
Considering the pros/cons people seem to have with the ideas discussed so far, I'm wondering...
What about "Null Exception Operator"?
Purely from an effective terminology perspective, to me
null exception operator
tells users exactly what they need to know by focusing on the end result that actually affects them (the exception thrown), while bypassing the contention around how exactly it's getting there (cast vs. assertion vs. check, etc.). It's clearly saying "this operator causes an exception on null".null failure
is similar, technically describing the outcome, but "failure" is vague; if we're choosing this we might as well be more explicit and just say what the failure is: an "exception".throw-if-null operator
is even more explicit, but I feel it's too far from the original terminology to be a contender and is kind of a mouth-full.non-null assertion
andnon-null check
are tied for second place for me, as they're the best combination of familiar/recognizable/accurate, but they're not perfect and there's clearly issue taken with both of them.Goals
null assertion operator
The text was updated successfully, but these errors were encountered: