Skip to content

Should spread collections support const? #63

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

Closed
munificent opened this issue Oct 25, 2018 · 10 comments
Closed

Should spread collections support const? #63

munificent opened this issue Oct 25, 2018 · 10 comments
Labels
enhanced-const Requests or proposals about enhanced constant expressions question Further information is requested

Comments

@munificent
Copy link
Member

The current "Spread Collections" proposal does not allow using spread in a const list. This is necessary in cases where the object you are spreading could do unexpected computation, like:

class InfiniteSequence implements Iterable<int> {
  const InfiniteSequence();

  Iterator<int> get iterator {
    return () sync* {
      var i = 0;
      while (true) yield i ++;
    }();
  }
}

const forever = [...InfiniteSequence()];

But in cases where the object being spread is an actual core library List object, the spread is safe. That's because it must be const (since it's inside a const context), and we have access to the actual value at compile time, not just its static type.

So we could say that you can spread inside a const list if and only if the spread object const-evaluates to a dart:core List.

Is this worth doing? Personally, I dislike adding yet more special cases for const shenanigans, and I rarely use const, so I'm not inclined. But if users feel it's important, I can see doing it.

@munificent munificent added the question Further information is requested label Oct 25, 2018
@matanlurey
Copy link
Contributor

So as one of the biggest users of const (AngularDart annotations), I'm not particularly excited by this change, that is, I wouldn't oppose it but am not sure it holds its own weight:

  • List.+ doesn't work on const either:

    const a = ['a'];
    const b = ['b'];
    const c = a + b;

If we were working on a general expansion of const, then I think this would be a logical addition. By itself, I'm not sure its really worth doing.

@natebosch
Copy link
Member

I dislike adding yet more special cases for const shenanigans

From a different viewpoint, not supporting this in const can be considered a special case. We're definitely accustomed to running up against limitations on what we can do in a const context, but having an entire syntax - not value or operation - off limits to me inside a literal would be surprising to me.

@lrhn
Copy link
Member

lrhn commented Oct 29, 2018

I'm on the fence here.

It's obviously doable. We are doing something similar with constant string interpolations.

There is a (philosohical) difference between strings and lists: to embed a list in another, you need to deconstruct it, which is something we otherwise never do in const expressions.

The distinction is philosophical, rather than real, because you actually also deconstruct strings into characters in order to embed it in another string, it's only because we see strings as atomic that it feels differently.

I can argue consistency either way: Allow it, like we allow constant string interpolations, because it's really the same thing, or disallow it like we disallow any other attempt to deconstruct a list.

I would require specifying exactly which lists/maps can be spread (only ones created by const list/map literals).

@leafpetersen
Copy link
Member

The distinction is philosophical, rather than real,

There's a real distinction too, which is that String is final, but List is not.

@lrhn
Copy link
Member

lrhn commented Oct 29, 2018

If by final, you mean the class cannot be subclassed, yes that is where we need to specify which constant Lists can be spread, like we specify which Symbol objects can be switch case expressions.

@munificent
Copy link
Member Author

like we specify which Symbol objects can be switch case expressions.

Ah, interesting. I see the spec says:

It is a compile-time error if the class C has an implementation of the operator
== other than the one inherited from Object unless the value of the
expression is a string, an integer, literal symbol or the result of invoking a
constant constructor of class Symbol.

Given that prior art, it seems a little more reasonable to me to do a similar restriction for List inside spreads and allow that.

@leafpetersen
Copy link
Member

Given that one of the main use cases motivating this feature is flutter and const is important to flutter, I'm fairly inclined to allow const spreads unless there are good reasons not to, or unless the flutter folks are opposed/don't think this would ever come up. @Hixie, @yjbanov any thoughts on this?

@Hixie
Copy link

Hixie commented Nov 2, 2018

I think all side-effect-free code should be allowed in const expressions.

@yjbanov
Copy link

yjbanov commented Nov 2, 2018

I agree with @Hixie that const expressions should be more expressive than they are right now. However, I'm not able to come up with any specific use-cases right now, so I can't comment on how important it is to implement this right away.

@munificent
Copy link
Member Author

OK, I'm convinced it's worth allowing ... in const collections when it makes sense: #82.

@eernstg eernstg added the enhanced-const Requests or proposals about enhanced constant expressions label Dec 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhanced-const Requests or proposals about enhanced constant expressions question Further information is requested
Projects
None yet
Development

No branches or pull requests

8 participants