Skip to content
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

Make ?. smarter #29499

Closed
kelegorm opened this issue Apr 27, 2017 · 8 comments
Closed

Make ?. smarter #29499

kelegorm opened this issue Apr 27, 2017 · 8 comments
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language).

Comments

@kelegorm
Copy link

kelegorm commented Apr 27, 2017

We have long chain like next one:

data?.properties.values.name

But Dart Analyzer tells me about warnings, it wants me to write that:

data?.properties?.values?.name

But this additional operators haven't any sense. I guess we should make ?. operator to skip all next chain and just return null in the end.

@matanlurey
Copy link
Contributor

I don't know if it makes sense to automatically add operators.

Though, maybe at minimum this should be a quick-fix in the analyzer? @bwilkerson

@bwilkerson
Copy link
Member

Yeah, a quick fix would be great.

@rakudrama rakudrama added the area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). label Apr 27, 2017
@MichaelRFairhurst
Copy link
Contributor

MichaelRFairhurst commented Apr 27, 2017 via email

@kelegorm
Copy link
Author

kelegorm commented Apr 27, 2017

@MichaelRFairhurst Yes, I know null has methods. But all sense of null that it's a just null. And you never know which one in a chain was null. So, it's still useless.

@MichaelRFairhurst
Copy link
Contributor

Well, its not useless if you intend to use the resulting null's members:

class Foo {                                                                      
  Foo foo;                                                                       
}                                                                                
                                                                                 
main() {                                                                         
  Foo a = null;                                                                  
  print(a?.foo.toString().length);                                               
} 

This doesn't have the lint error, it recognizes that "null" has "toString", and that "toString" produces "length".

That said, it's worth noting that

a?.b.c has fewer null checks than a?.b?.c. So in theory it could be faster. And you might still need a?.b?.c in your code even if the behavior of ?. were updated as suggested here.

@rakudrama
Copy link
Member

The problem is that the meaning of a?.b is defined independently of its use.
So a?.b.c is the same as (a?.b).c
The definition of null-aware expressions is 'compositional' at too small a unit.

I too would prefer the whole chain was treated as a null-aware unit.
It is annoying to have to write a?.b?.c, especially when I know the result of get b can never be null (or should never be null and I want an error if it is).

Not only is the current definition mismatched to what many users expect, it also causes the generated code to be bigger and slower than necessary.
Give the choice of writing a == null ? a : a.b.c or a?.b?.c I will probably write the second, but it involves an unnecessary check on the result of get b. The dart2js output for our largest applications contain many hundreds of these unnecessary checks.

(a && b && c has a similar problem (that the result of a && b is tested again) but this is much less serious, and since it involves no calls on null values, the compiler can do some work to treat (a && b) && c as if it was written a && (b && c).)

I think we should revisit the definition of ?.. A slightly more complicated definition that short-circuited the group would be more useful for programmers, which is why we created a new language in the first place.

@lrhn
Copy link
Member

lrhn commented Apr 28, 2017

We are aware of the problem (and I do find it annoying myself :). I hope we'll be able to do something about it at a later point, but sadly it's currently not at the front of the priority queue.

What about x?.y.toString(), should it return null or call toString on null? Probably the former, so we need to be able to delimit the guard again, say with (x?.y).toString() not being guarded by the ?..
We probably also don't want to continue into operators, so x?.y + 4 does try to add 4 to null. On the other hand, assignments would work: x?.y.z = 42 would skip the assignment. Basically, we are looking at something like the selectors after a cascade, but as usual, details might contain devils.

@srawlins
Copy link
Member

Duplicate of #26240

@srawlins srawlins marked this as a duplicate of #26240 Oct 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language).
Projects
None yet
Development

No branches or pull requests

7 participants