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 it easy/efficient to create immutable collections via literals #117

Open
kevmoo opened this issue Nov 29, 2018 · 5 comments
Open

Make it easy/efficient to create immutable collections via literals #117

kevmoo opened this issue Nov 29, 2018 · 5 comments
Labels
request Requests to resolve a particular developer problem

Comments

@kevmoo
Copy link
Member

kevmoo commented Nov 29, 2018

See

https://github.com/dart-lang/sdk/blob/031e77eea11a16a5e486a3673549adbd68862c8e/sdk/lib/core/uri.dart#L2233-L2237

      // ASCII, a single percent encoded sequence.
      codeUnits = new List(3);
      codeUnits[0] = _PERCENT;
      codeUnits[1] = _hexDigits.codeUnitAt(char >> 4);
      codeUnits[2] = _hexDigits.codeUnitAt(char & 0xf);

Also in the SDK,
2x in this file https://github.com/dart-lang/sdk/blob/031e77eea11a16a5e486a3673549adbd68862c8e/sdk/lib/vmservice/message.dart#L176-L182

4x in this file https://github.com/dart-lang/sdk/blob/031e77eea11a16a5e486a3673549adbd68862c8e/runtime/bin/vmservice/loader.dart#L1107-L1112

This entire file in pkg:isolate - https://github.com/dart-lang/isolate/blob/master/lib/src/util.dart

In the Dart sources in Google (some of these duplicate the above)

  • List.unmodifiable\(\[ - 135 hits
  • List\<.+\>\.unmodifiable\(\[ - 96 times
  • Map\<.+,.+>\.unmodifiable\(\{ - 25 times
  • Map\.unmodifiable\(\{ - 28 times
  • UnmodifiableSetView from pkg:collection is used dozens of times, not as a view over mutable data, but as a immutable set.

Benefits:

  • Less copying!
  • Immutable collections are more efficient
    • iteration doesn't need to track version, etc
    • no need to have indirection to a fixed-sized backing store to support growing
  • Enables special-casing implementations - e.g. immutable([1,2,3]) could be created as Uint8List.
@kevmoo kevmoo added the request Requests to resolve a particular developer problem label Nov 29, 2018
@yjbanov
Copy link

yjbanov commented Nov 29, 2018

Related: dart-lang/sdk#27755

In Flutter as soon as you pass a collection of objects, typically a List<Widget> but not always, to a widget, conceptually you are giving up write ownership to that list. IOW, the list becomes read-only. It is a common mistake to pass a list, mutate it, then expect Flutter to update the UI correctly. Nothing in the type system of collections prevents this mistake, and it is a very natural one to make when you are coming from a non-functional world.

@kevmoo
Copy link
Member Author

kevmoo commented Nov 29, 2018

CC @lrhn, who has written a bit of the code that created fixed-size lists for efficiency.

@munificent
Copy link
Member

The first four examples you link to don't create read-only lists, they create mutable fixed-size ones. Likewise, uses of unmodifiable() and friends don't always create immutable lists, they create read-only views of an otherwise mutable list. In many cases, that view is the only way to get to the list, so it is effectively immutable, but that's not true for some unknown fraction of those cases.

I really think we need to be clear and explicit when we talk about this. I know of, at least:

  • Fixed-size lists — you can change elements but not the length. This matters because if the list can never be resized than internally you don't need an extra indirection between the list object and its backing storage.

  • Constant lists — it contains only data known at compile time and the contents never change.

  • Immutable lists — once created, no piece of data in it ever changes. It may contain data known only at runtime.

  • Frozen lists — the list can be mutated for a while. Then at some point, it gets locked down and further changes are prohibited (usually by way of a runtime error).

  • Read-only views — some code is given an object that lets them access the list's data but not modify it. Other code may be able to modify that same list in which cases even users of the read-only view may observe that modification.

  • Persistent lists — you can "modify" the list but doing so always creates a new list and the API for working with the list reflects that explicitly (i.e. add() returns a List, not void). References to the original list never see the change.

  • Copy-on-write lists — if you pass a list to another function, it is passed efficiently without copying it eagerly. But if that function modifies the list, the list is copied and only that function sees the modification. The list that the caller has is left unchanged.

Each of these has different use cases, affordances, and constraints. Before we go in the direction of any of these (beyond what we already have), I think we need clearer data about which specific goals users have.

@kevmoo kevmoo changed the title Make it easy/efficient to create read-only collection literals Make it easy/efficient to create immutable collections via literals Nov 29, 2018
@kevmoo
Copy link
Member Author

kevmoo commented Nov 29, 2018

Updated the title to explicitly call out "immutable". Even in the cases in the SDK where we're creating (strictly speaking) fixed-sized lists, immutable would be more desirable.

@kevmoo
Copy link
Member Author

kevmoo commented Sep 15, 2022

See also #2477

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests

3 participants