-
Notifications
You must be signed in to change notification settings - Fork 205
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
Non-growable list literal syntax #2477
Comments
I love the idea. I am not sold on this syntax, tho. |
var items = @fixedLength <int>[1, 2, 3]; |
My investigation into non-growable lists stemmed from @mkustermann 's analysis at dart-lang/sdk#49858. I have mailed out dart-lang/dartdoc#3151 for dartdoc which indicates a ~7% memory use reduction in documenting one package. And there is this change which saved a ton of memory for dart2js. Other than these examples, I don't have super rigorous data on the benefits of the non-growable list. |
I use non-growable lists by default. Although for many cases the difference is negligible, the cost to have this little optimization is also negligible, i.e. just put a However, I know of some people that would think it's verbose and even refuse to use Another problem with non-growable lists, although not in the scope of this issue, is that we can't statically avoid that it grows. If we had a |
This looks really helpful. It seems like an unusual restriction on an otherwise mutable concept, but I'd regard it similarly to |
I'd be all for a way to select the kind of list you create. The default is already available, but I'd want both unmodifiable and fixed-length. Maybe we can use Using the suffix idea, we can do Using a prefix would be nice because then we can also apply it to strings. Syntax is hard, let's do math! |
See also https://github.com/tc39/proposal-record-tuple. Their syntax is I'd take |
A non-growable list can still be mutable, so it is not quite the same request. I would definitely like to see collection literal syntax (with collection-for, collection-if, spreads ...) work with a greater variety of collection types. Iterable literals #1633 are another example where I think collection literal syntax would be nice. |
Generalizing collection literal syntax seems like a useful thing. We'd need to open it up to any user collection class. Say something like Then we can special-case the platform constructors to do things normal classes can't (or at least do it more efficiently, without having to go through an iterator). Which means |
I really like Another syntax idea: who says we can't have named arguments in |
About "named parameters" in literals, that won't fly for unmodifiable set literals like |
I like the |
Hello @lrhn, Im unable to understand, that in the comment, does Thanks |
Hello everyone, I think:
Also, I think there is no real benefit in adding The last point of syntax pollution, is actually very important now, as we see more and more request issues, to add useless features, with ugly syntax, to dart, Just my opinion, |
Please explain, I seek Peace, |
Regarding replacing
I understand the cost/benefit ratio argument, for a critical breaking change, but:
Thanks |
My idea with
In the latter case, Ok, I like 2. better. I don't need a way to specify UTF-8 bytes directly, but I do want a way to specify (In either case, the string must be a constant, so it can only contain constant string interpolations.) Also, about |
From this issue(regarding
This could be a good opportunity, to add Thanks |
I like the idea of having an I'm not sure I like the idea that the only way to define a byte list literal would be with a string using ASCII code. It would end up being not very intuitive to use and only really sensible for situations where you're specifically using bytes in a string context. Any other situation would make it really undesirable in context, for example, if I had a byte array I wanted to use as a default header for generated WAV files: final wavHeader = u8'RIFF\x14`(\x00WAVEfmt\x20\x10\x00\x00\x00\x01\x00\x01\x00"V\x00\x00D\xac\x00\x00\x02\x00\x10\x00data\xf0_(\x00'; If I ever wanted to change a couple of the bytes in the literal, it would be nontrivial to decipher that string to find the byte I wanted to modify and then know the exact ASCII character that I needed to change it to. On the other hand, a list in plain list literal syntax with either base10 or base16 integers is simple to understand and modify, even if it's not great on conciseness. Having the final u8 = ['a', 'b' ,'c'];
final foo = u8[1]; // array literal or indexer?
// is `foo` inferred to be a String or a Uint8List? I don't see getting around the issue that pushing this feature would require a breaking change that "u8" would become a reserved keyword in order to resolve this. One possible solution that comes to mind is to use the type parameter to specify literals of various numerical type literals:
It's unambiguous, but the problem now is that this would require all of the numeric "primitives" to have type names in the global space, increasing pollution and possibly breaking some codebases. It would also be confusing that you could use Maybe just add all the other fully-featured numeric primitives themselves to Dart? Sounds simple enough. /s |
My biggest issue is that you do I wish something like abstract class BaseList {}
class List implements BaseList {}
class ImmutableList implements BaseList {}
class FixedList implements BaseList {} // or extends List So ImuutableList doesn't have |
Perhaps inline classes could be used so we'd have: inline class ImmutableList<T> {
ImmutableList(this.list);
final List<T> list;
} This way, it'd be zero-cost and you wouldn't be able to call mutating methods on this |
I had a ton of bugs from JsonSerializable due to this, I never know if a parameter is mutable or immutable. Took me a lot of tries and a many bugs :(. It is worth considering if this/other solutions would 'fix' JsonSerializable. |
Interestingly, as far as I know, this is already how lists are represented internally, at least in the Dart VM. (Not sure about the web/JS side.) That said, exposing it might not be so trivial - I'd imagine if it was, they would've already done so a while ago. That said, I can't imagine it would be that difficult to add a I'm curious how a list's (im)mutability would pose a problem with JsonSerializable though. Typically a list wouldn't be modified during the serialization process and I can't think of a reason why it would be. |
I think they simplified because they wanted, but now it is time to unsimplify again. The issue is that all classes need to have const default parameters (ideally), so if it is null it becomes |
@bernaferrari Ohhh yes. It's annoying to have a runtime error when trying to add an element to an immutable List, it happens all the time in Java. I guess it's a better idea to have an Array class that is an immutable List, but a completely unrelated type; instead of trying to have the same name for classes that behave differently in a very special way. |
If |
In the meantime, this can be used as a workaround: extension ImmutableListExtension<T> on List<T> {
bool get isMutable {
try {
addAll(const []);
return true;
} catch (e) {
return false;
}
}
} It's not ideal since it relies on a try-catch, but AFAIK there is no way to know if an EDIT: Wow, okay. I already said the workaround wasn't ideal, but if a better workaround exists, by all means, someone please post it. Otherwise, I don't understand the down thumbs seeing as people are literally explaining how this behavior is an impedance and frustration, and until an official method is introduced (which doesn't rely on mirrors since Flutter devs can't use that), there isn't really a better option than a stupid little try-catch wrapper. I mean, sure, we can say it's better to refactor the code so it doesn't happen in the first place, but that's not something that can always be guaranteed when packages and third-party code come into play. So when code can completely break in an unintuitive and undetectable way simply due to a tiny change to how it's used... // Imagine this class was buried in a package somewhere
class Foo {
final List<int> list;
Foo([this.list = const [0]]);
}
void main() {
final a = Foo([0]);
print(a.list); // Prints "[0]"
print(a.list.runtimeType); // Prints "List<int>"
a.list.add(1); // Completely fine
final b = Foo();
print(b.list); // Prints "[0]"
print(b.list.runtimeType); // Prints "List<int>"
b.list.add(1); // Throws a runtime error
} ...then there is a fundamental issue. Two lists in two instances of the same class that otherwise appear identical will behave differently at runtime, creating a time bomb that cannot possibly be checked for before it goes off. There is no That isn't just problematic, it's borderline unacceptable. |
Hello everyone, The new syntax, being proposed here, is:
Problem with the proposed syntaxThe reserved words, SolutionOnce #1014 gets implemented, then we would be able to add the following:
thanks |
I think #1014, is difficult to approve for dart team, as useless, in front of thanks |
The idea for The note on
This would be a fundamental syntactic change in how lists are constructed in Dart, and personally, I'm against such a drastic change unless the Dart team had no other choice. Furthermore, it has already been said that a likely re-use of the soon-to-be-removed default
I would hazard a guess that this change would break 90%+ of the code in packages or in production everywhere. It's a non-starter. |
I think, Also I think, inference is the root cause of all the problems, here If it weren't there, then we could do both, thanks |
Personally, I like the idea of there being a Also, |
We could do something like a function call syntax for it: final fixedLengthList = [
// ...
](growable: false); |
Inventing a special ad-hoc syntax for the literals won't get you very far. There should be a systematic way of adding properties to the language constructs of any kind, be it literals, keywords or anything. The |
This syntax is problematic for many reasons, most notably because it would run afoul of Dart’s convention to make any type callable by adding a Implementing meta-programming isn’t a trivial undertaking, and the biggest reason the Dart team hasn’t worked on it thus far is because they had other higher priorities. They are working on it now to a degree, but it will likely be a very long time if ever before it can support what you’re suggesting. (And as an irrelevant aside, I have no idea how |
Non-growable lists are implemented more efficiently than growable lists, but creating one is rather verbose and inconvenient.
Oh! to give up our precious and novel UI-as-code, our spreads and for-elements and if-elements...☹️ And we're forced to create an intermediate 1-element list with
followedBy([lastThing])
, and I didn't even implement theif (condition)
part.Solution
What a beautiful, space-efficient, fun and quirky world we'd live in, if we had a non-growable list literal syntax. I'm thinking:
Or if we want to reserve
gf
for a gluten-free option, we can use[]ng
("non-growable"),[]f
("fixed-length"), whatever. A precedingf
would be great (f[]
), but I can't see how that wouldn't blatantly conflict with index-expressions.The text was updated successfully, but these errors were encountered: