-
Notifications
You must be signed in to change notification settings - Fork 1.7k
A better approach to express collection mutability #50888
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
Comments
cc @lrhn |
This is not a new idea. Heavens know I've had it many times myself. 😁 The dragons are in the details. Starting with naming (which is probably also the easiest to fix). Here you suggest that final ImmutableList<int> l = [1, 2, 3];
(l as List<int>).add(4); // Gotcha! That's because It would be better to have Or abstract class Iterable<T> { ... }
abstract class Vector<T> implements Iterable<T> {
T operator[](int index);
// ...
}
abstract class List<T> implements Vector<T> {
operator[]=(int index, T value);
// ...
} Then you can do: void onlyReading(Vector<int> numbers) {
// random access reading numbers
}
void updateToo(List<int> numbers) {
int.add(42); // Because I can!
}
void main() {
List<int> ns = [1, 2, 3];
onlyReading(ns); // Valid, probably only reads.
updateToo(ns); // Valid, expect it to write.
} Where this becomes an issue is that it means everybody has to decide, up front, whether to accept a More crucial, any method returning a list need to decide whether it's a That's what makes this change unlikely to happen. It will be incredibly hard to migrate all existing code to this behavior. Every method which goes from returning We might need a completely new composite type system, like for null safety, where It's still a big migration. Code can't just change to returning immutable Some functions simply cannot be migrated, like I'm not as opposed to the idea as I have been. It's clearly in the direction that Dart has already been moving for a while. But it's not trivial to get right, and it's a massive migration challenge. |
You are right about the negative modifier being a problem. In my first approach I indeed started with this: abstract class List<E> {...}
abstract class MutableList<E> implements List<E>, MutableCollection<E> {...} But unfortunately, I knew that would be a huge breaking change on the current dart:core library API (List is immutable here, and nowdays List is mutable). I didn't find a better name like After some research I found that Kotlin follows this same approach: interface List<out E> : Collection<E>
interface MutableList<E> : List<E>, MutableCollection<E> Which would "solve" the first problem (the example intention is different though): final MutableList<int> l = [1, 2, 3];
(l as List<int>).add(4); // safe cast MutableList<int> as List<int> but compile error, List does not implement add
final List<int> l2 = [1,2,3];
(l2 as MutableList<int>).add(4) // unsafe cast, fails at runtime Kotlin also seems to have So I think all of your suggestions are similar do Kotlin, and I gotta say it but it feels much better to work with collections in there than Dart unfortunately. Personally, since the Dart 1 to Dart 2 shift, I feel many core elements/libraries feels like a patch and would need a rewrite to align with the new Dart 2 paradigm obtained via NNBD, a stronger type system, etc... The compromise I see here is: a) Keep the outdated approach, which is less safe and delegates many things to the runtime system (slower). In exchange, we don't have many breaking changes. b) Call some breaking changes, developers need to adapt, but in principle, get a language more aligned with the characteristics and features of Dart 2. I think we can't have both, it's up to the Dart team to decide ofc. I don't like to feel that Dart 1 born crooked. The Dart team is taking a lot of effort (Great job BTW) on new features and I feel that the core API should not fall behind. |
This is a surprising behavior for a lot of people. They make a Most of the time they will notice before releasing to production, but it's still something that we could prevent statically. Just yesterday, a user asked for help on Discord regarding this code: /// Class to execute router updates in a centralized way.
///
/// Each sub-router must register a listener that updates them.
/// This is done by setting the [BeamerDelegate.updateListenable] parameter.
class SubRoutersUpdateListenable extends Listenable {
// const SubRoutersUpdateListenable();
SubRoutersUpdateListenable();
final _listeners = const <VoidCallback>{};
@override
void addListener(VoidCallback listener) => _listeners.add(listener);
@override
void removeListener(VoidCallback listener) => _listeners.remove(listener);
void execute() {
for (final listener in _listeners) {
listener();
}
}
} He actually understood what was happening, but not why. Our discussion resulted more or less in what have been discussed here:
Either way, I think this breakage is valuable for a major version. We could obviously seek for a less-breaking migrating process, and |
I don't actually expect this change to happen. Not saying it cannot, but it's a breaking change on a scale that's very hard to argue will be worth the pain. Also, it's so much work that it's hard to argue that the opportunity cost is worth it, compared to other changes. Let's imagine for a moment that we did want to make this change.
Each will have the same general constructors as All Typed Data lists will implement That was the easy part. 😓 Then we go through every function that accepts or returns Most of the arguments, probably all, should just become Most of the returns should likely be And every existing method with a Then all user code in existence will break. So we make a hack and let pre-feature code treat an occurrence of the type When assigning a pre-feature It's like unsafe nullable types all over again: The two language versions do not agree on how many types there are, some of them are collapsed in the legacy code. In this case, it's not as ubiquitous as nullable types, there isn't a growable and non-growable version of every type, it's just one small, fixed type hierarchy. Migration will then likely be changing most (Then we should consider doing the same thing for The occurrences of sdk/lib/collection/collections.dart:31: List<R> cast<R>() => UnmodifiableListView(_source.cast<R>());
sdk/lib/collection/list.dart:223: List<E> toList({bool growable = true}) {
sdk/lib/collection/list.dart:310: List<R> cast<R>() => List.castFrom<E, R>(this);
sdk/lib/collection/list.dart:345: List<E> operator +(List<E> other) => [...this, ...other];
sdk/lib/collection/list.dart:347: List<E> sublist(int start, [int? end]) {
sdk/lib/collection/list.dart:555: static String listToString(List<Object?> list) =>
sdk/lib/collection/queue.dart:710: List<E> toList({bool growable = true}) {
sdk/lib/collection/set.dart:118: List<E> toList({bool growable = true}) =>
sdk/lib/convert/ascii.dart:51: String decode(List<int> bytes, {bool? allowInvalid}) {
sdk/lib/convert/ascii.dart:172: String convert(List<int> bytes, [int start = 0, int? end]) {
sdk/lib/convert/ascii.dart:264: void add(List<int> source) {
sdk/lib/convert/ascii.dart:268: void addSlice(List<int> source, int start, int end, bool isLast) {
sdk/lib/convert/ascii.dart:294: void add(List<int> source) {
sdk/lib/convert/ascii.dart:303: void addSlice(List<int> source, int start, int end, bool isLast) {
sdk/lib/convert/base64.dart:41:String base64Encode(List<int> bytes) => base64.encode(bytes);
sdk/lib/convert/base64.dart:46:String base64UrlEncode(List<int> bytes) => base64Url.encode(bytes);
sdk/lib/convert/base64.dart:240: String convert(List<int> input) {
sdk/lib/convert/base64.dart:312: Uint8List? encode(List<int> bytes, int start, int end, bool isLast) {
sdk/lib/convert/base64.dart:335: static int encodeChunk(String alphabet, List<int> bytes, int start, int end,
sdk/lib/convert/base64.dart:420: void add(List<int> source) {
sdk/lib/convert/base64.dart:428: void addSlice(List<int> source, int start, int end, bool isLast) {
sdk/lib/convert/byte_conversion.dart:28: void addSlice(List<int> chunk, int start, int end, bool isLast) {
sdk/lib/convert/byte_conversion.dart:48: void add(List<int> chunk) {
sdk/lib/convert/json.dart:442: List<int> convert(Object? object) {
sdk/lib/convert/json.dart:838: void writeList(List<Object?> list) {
sdk/lib/convert/json.dart:891: void writeList(List<Object?> list) {
sdk/lib/convert/latin1.dart:50: String decode(List<int> bytes, {bool? allowInvalid}) {
sdk/lib/convert/latin1.dart:146: void add(List<int> source) {
sdk/lib/convert/latin1.dart:159: void addSlice(List<int> source, int start, int end, bool isLast) {
sdk/lib/convert/latin1.dart:199: void addSlice(List<int> source, int start, int end, bool isLast) {
sdk/lib/convert/line_splitter.dart:52: List<String> convert(String data) {
sdk/lib/convert/string_conversion.dart:261: void add(List<int> chunk) {
sdk/lib/convert/string_conversion.dart:299: void add(List<int> chunk) {
sdk/lib/convert/string_conversion.dart:303: void addSlice(List<int> chunk, int startIndex, int endIndex, bool isLast) {
sdk/lib/convert/utf.dart:58: String decode(List<int> codeUnits, {bool? allowMalformed}) {
sdk/lib/convert/utf.dart:348: String convert(List<int> codeUnits, [int start = 0, int? end]) =>
sdk/lib/convert/utf.dart:547: external String convertSingle(List<int> codeUnits, int start, int? maybeEnd);
sdk/lib/convert/utf.dart:549: external String convertChunked(List<int> codeUnits, int start, int? maybeEnd);
sdk/lib/core/function.dart:144: external static apply(Function function, List<dynamic>? positionalArguments,
sdk/lib/core/invocation.dart:62: List<Type> get typeArguments => const <Type>[];
sdk/lib/core/invocation.dart:68: List<dynamic> get positionalArguments;
sdk/lib/core/iterable.dart:497: List<E> toList({bool growable = true}) =>
sdk/lib/core/list.dart:260: static List<T> castFrom<S, T>(List<S> source) => CastList<S, T>(source);
sdk/lib/core/list.dart:276: static void copyRange<T>(List<T> target, int at, List<T> source,
sdk/lib/core/list.dart:311: static void writeIterable<T>(List<T> target, int at, Iterable<T> source) {
sdk/lib/core/list.dart:342: List<R> cast<R>();
sdk/lib/core/list.dart:716: List<E> operator +(List<E> other);
sdk/lib/core/list.dart:739: List<E> sublist(int start, [int? end]);
sdk/lib/core/pattern.dart:130: List<String?> groups(List<int> groupIndices);
sdk/lib/core/string.dart:669: List<String> split(Pattern pattern);
sdk/lib/core/string.dart:700: List<int> get codeUnits;
sdk/lib/core/uri.dart:443: factory Uri.dataFromBytes(List<int> bytes,
sdk/lib/core/uri.dart:527: List<String> get pathSegments;
sdk/lib/core/uri.dart:3480: factory UriData.fromBytes(List<int> bytes,
sdk/lib/core/uri.dart:4571: List<String> get pathSegments {
sdk/lib/developer/http_profiling.dart:26:List<Map<String, dynamic>> getHttpClientProfilingData() {
sdk/lib/ffi/ffi.dart:213: const factory Array.variableMulti(List<int> dimensions) =
sdk/lib/html/dart2js/html_dart2js.dart:1328: List<BackgroundFetchSettledFetch>? get fetches native;
sdk/lib/html/dart2js/html_dart2js.dart:1443: List<BackgroundFetchSettledFetch>? get fetches native;
sdk/lib/html/dart2js/html_dart2js.dart:1559: List<String>? get platforms native;
sdk/lib/html/dart2js/html_dart2js.dart:1600: factory Blob(List blobParts, [String? type, String? endings]) {
sdk/lib/html/dart2js/html_dart2js.dart:1968: List<Node>? get labels native;
sdk/lib/html/dart2js/html_dart2js.dart:2059: List? get methodData native;
sdk/lib/html/dart2js/html_dart2js.dart:2061: List? get modifiers native;
sdk/lib/html/dart2js/html_dart2js.dart:2928: List<num> getLineDash() {
sdk/lib/html/dart2js/html_dart2js.dart:2943: void setLineDash(List<num> dash) {
sdk/lib/html/dart2js/html_dart2js.dart:3231: List<Node> getDistributedNodes() native;
sdk/lib/html/dart2js/html_dart2js.dart:3543: List<CssRule>? get cssRules native;
sdk/lib/html/dart2js/html_dart2js.dart:3613: List<CssRule>? get cssRules native;
sdk/lib/html/dart2js/html_dart2js.dart:8726: List<CssRule> get cssRules native;
sdk/lib/html/dart2js/html_dart2js.dart:8732: List<CssRule>? get rules native;
sdk/lib/html/dart2js/html_dart2js.dart:9119: List<Node>? get options native;
sdk/lib/html/dart2js/html_dart2js.dart:9147: List<File>? get files native;
sdk/lib/html/dart2js/html_dart2js.dart:9151: List<String>? get types native;
sdk/lib/html/dart2js/html_dart2js.dart:9428: List? get cornerPoints native;
sdk/lib/html/dart2js/html_dart2js.dart:9450: List? get landmarks native;
sdk/lib/html/dart2js/html_dart2js.dart:9470: List? get cornerPoints native;
sdk/lib/html/dart2js/html_dart2js.dart:10092: List<Animation> getAnimations() native;
sdk/lib/html/dart2js/html_dart2js.dart:10096: List<Node> getElementsByClassName(String classNames) native;
sdk/lib/html/dart2js/html_dart2js.dart:10100: List<Node> getElementsByName(String elementName) native;
sdk/lib/html/dart2js/html_dart2js.dart:10104: List<Node> getElementsByTagName(String localName) native;
sdk/lib/html/dart2js/html_dart2js.dart:10139: List<Element> elementsFromPoint(int x, int y) native;
sdk/lib/html/dart2js/html_dart2js.dart:10489: List<Element> get children {
sdk/lib/html/dart2js/html_dart2js.dart:10496: set children(List<Element> value) {
sdk/lib/html/dart2js/html_dart2js.dart:10614: List<StyleSheet>? get styleSheets native;
sdk/lib/html/dart2js/html_dart2js.dart:10618: List<Element> elementsFromPoint(int x, int y) native;
sdk/lib/html/dart2js/html_dart2js.dart:13046: set children(List<Element> value) {
sdk/lib/html/dart2js/html_dart2js.dart:13246: List<Rectangle> getClientRects() {
sdk/lib/html/dart2js/html_dart2js.dart:14730: List<Animation> getAnimations() native;
sdk/lib/html/dart2js/html_dart2js.dart:14738: List<String> getAttributeNames() native;
sdk/lib/html/dart2js/html_dart2js.dart:14785: List<Node> getDestinationInsertionPoints() native;
sdk/lib/html/dart2js/html_dart2js.dart:14798: List<Node> getElementsByClassName(String classNames) native;
sdk/lib/html/dart2js/html_dart2js.dart:15574: List<EventTarget> get path =>
sdk/lib/html/dart2js/html_dart2js.dart:15648: List<EventTarget> composedPath() native;
sdk/lib/html/dart2js/html_dart2js.dart:15919: List<MessagePort>? get ports native;
sdk/lib/html/dart2js/html_dart2js.dart:16054: List<Node>? get elements native;
sdk/lib/html/dart2js/html_dart2js.dart:16087: factory File(List<Object> fileBits, String fileName, [Map? options]) {
sdk/lib/html/dart2js/html_dart2js.dart:16637: List<FontFace>? get fontfaces native;
sdk/lib/html/dart2js/html_dart2js.dart:16712: List<Object> getAll(String name) native;
sdk/lib/html/dart2js/html_dart2js.dart:16825: List<num>? get axes native;
sdk/lib/html/dart2js/html_dart2js.dart:16829: List<GamepadButton>? get buttons native;
sdk/lib/html/dart2js/html_dart2js.dart:19162: List<File>? get files native;
sdk/lib/html/dart2js/html_dart2js.dart:19164: set files(List<File>? value) native;
sdk/lib/html/dart2js/html_dart2js.dart:19202: List<Node>? get labels native;
sdk/lib/html/dart2js/html_dart2js.dart:19303: List<Entry>? get entries native;
sdk/lib/html/dart2js/html_dart2js.dart:19363: List<Node>? get labels;
sdk/lib/html/dart2js/html_dart2js.dart:19790: List<File>? files;
sdk/lib/html/dart2js/html_dart2js.dart:19928: List<num>? get thresholds native;
sdk/lib/html/dart2js/html_dart2js.dart:19934: List<IntersectionObserverEntry> takeRecords() native;
sdk/lib/html/dart2js/html_dart2js.dart:20375: List<String>? get ancestorOrigins native;
sdk/lib/html/dart2js/html_dart2js.dart:20481: List<Node> get areas native;
sdk/lib/html/dart2js/html_dart2js.dart:21009: List? get artwork native;
sdk/lib/html/dart2js/html_dart2js.dart:21011: set artwork(List? value) native;
sdk/lib/html/dart2js/html_dart2js.dart:21274: List<MediaStreamTrack> getAudioTracks() native;
sdk/lib/html/dart2js/html_dart2js.dart:21278: List<MediaStreamTrack> getTracks() native;
sdk/lib/html/dart2js/html_dart2js.dart:21282: List<MediaStreamTrack> getVideoTracks() native;
sdk/lib/html/dart2js/html_dart2js.dart:21613: List<MessagePort> get ports native;
sdk/lib/html/dart2js/html_dart2js.dart:21795: List<Node>? get labels native;
sdk/lib/html/dart2js/html_dart2js.dart:22430:typedef void MutationCallback(List mutations, MutationObserver observer);
sdk/lib/html/dart2js/html_dart2js.dart:22496: List<MutationRecord> takeRecords() native;
sdk/lib/html/dart2js/html_dart2js.dart:22591: List<Node>? get addedNodes native;
sdk/lib/html/dart2js/html_dart2js.dart:22605: List<Node>? get removedNodes native;
sdk/lib/html/dart2js/html_dart2js.dart:22641: List<Gamepad?> getGamepads() {
sdk/lib/html/dart2js/html_dart2js.dart:22877: List<String>? get languages native;
sdk/lib/html/dart2js/html_dart2js.dart:22959: List<String>? get languages native;
sdk/lib/html/dart2js/html_dart2js.dart:23211: List<Node> get nodes {
sdk/lib/html/dart2js/html_dart2js.dart:23297: List<Node> get childNodes native;
sdk/lib/html/dart2js/html_dart2js.dart:23808: List? get actions native;
sdk/lib/html/dart2js/html_dart2js.dart:23842: List<int>? get vibrate native;
sdk/lib/html/dart2js/html_dart2js.dart:24243: List<num> getLineDash() native;
sdk/lib/html/dart2js/html_dart2js.dart:24290: void setLineDash(List<num> dash) native;
sdk/lib/html/dart2js/html_dart2js.dart:24441: List<num>? get quaternion native;
sdk/lib/html/dart2js/html_dart2js.dart:24481: List<Node>? get labels native;
sdk/lib/html/dart2js/html_dart2js.dart:24664: List<num> getLineDash() native;
sdk/lib/html/dart2js/html_dart2js.dart:24681: void setLineDash(List<num> dash) native;
sdk/lib/html/dart2js/html_dart2js.dart:24935: List<String>? get addressLine native;
sdk/lib/html/dart2js/html_dart2js.dart:25011: factory PaymentRequest(List<Map> methodData, Map details, [Map? options]) {
sdk/lib/html/dart2js/html_dart2js.dart:25079: List? get methodData native;
sdk/lib/html/dart2js/html_dart2js.dart:25081: List? get modifiers native;
sdk/lib/html/dart2js/html_dart2js.dart:25185: List<PerformanceEntry> getEntries() native;
sdk/lib/html/dart2js/html_dart2js.dart:25187: List<PerformanceEntry> getEntriesByName(String name, String? entryType)
sdk/lib/html/dart2js/html_dart2js.dart:25190: List<PerformanceEntry> getEntriesByType(String entryType) native;
sdk/lib/html/dart2js/html_dart2js.dart:25271: List<TaskAttributionTiming>? get attribution native;
sdk/lib/html/dart2js/html_dart2js.dart:25398: List<PerformanceEntry> getEntries() native;
sdk/lib/html/dart2js/html_dart2js.dart:25400: List<PerformanceEntry> getEntriesByName(String name, String? entryType)
sdk/lib/html/dart2js/html_dart2js.dart:25403: List<PerformanceEntry> getEntriesByType(String entryType) native;
sdk/lib/html/dart2js/html_dart2js.dart:25457: List<PerformanceServerTiming>? get serverTiming native;
sdk/lib/html/dart2js/html_dart2js.dart:25575: Future<PermissionStatus> requestAll(List<Map> permissions) =>
sdk/lib/html/dart2js/html_dart2js.dart:25596: List? get fillLightMode native;
sdk/lib/html/dart2js/html_dart2js.dart:25753: List<PointerEvent> getCoalescedEvents() native;
sdk/lib/html/dart2js/html_dart2js.dart:25986: List<PresentationConnection>? get connections native;
sdk/lib/html/dart2js/html_dart2js.dart:26087: List<Node>? get labels native;
sdk/lib/html/dart2js/html_dart2js.dart:26417: List<Rectangle> getClientRects() {
sdk/lib/html/dart2js/html_dart2js.dart:26589:typedef void ResizeObserverCallback(List entries, ResizeObserver observer);
sdk/lib/html/dart2js/html_dart2js.dart:26618: List<Map> getFingerprints() native;
sdk/lib/html/dart2js/html_dart2js.dart:26855: List<String> names() native;
sdk/lib/html/dart2js/html_dart2js.dart:27087: List<MediaStream> getLocalStreams() native;
sdk/lib/html/dart2js/html_dart2js.dart:27089: List<RtcRtpReceiver> getReceivers() native;
sdk/lib/html/dart2js/html_dart2js.dart:27091: List<MediaStream> getRemoteStreams() native;
sdk/lib/html/dart2js/html_dart2js.dart:27093: List<RtcRtpSender> getSenders() native;
sdk/lib/html/dart2js/html_dart2js.dart:27213: List<RtcRtpContributingSource> getContributingSources() native;
sdk/lib/html/dart2js/html_dart2js.dart:27334: List<RtcLegacyStatsReport> result() native;
sdk/lib/html/dart2js/html_dart2js.dart:27356: List<MediaStream>? get streams native;
sdk/lib/html/dart2js/html_dart2js.dart:27655: List<Node>? get labels native;
sdk/lib/html/dart2js/html_dart2js.dart:27709: List<OptionElement> get options {
sdk/lib/html/dart2js/html_dart2js.dart:27714: List<OptionElement> get selectedOptions {
sdk/lib/html/dart2js/html_dart2js.dart:28042: List<Node> getDistributedNodes() native;
sdk/lib/html/dart2js/html_dart2js.dart:28082: List<StyleSheet>? get styleSheets native;
sdk/lib/html/dart2js/html_dart2js.dart:28086: List<Element> elementsFromPoint(int x, int y) native;
sdk/lib/html/dart2js/html_dart2js.dart:28266: List<Node> assignedNodes([Map? options]) {
sdk/lib/html/dart2js/html_dart2js.dart:28823: List<SpeechRecognitionResult>? get results native;
sdk/lib/html/dart2js/html_dart2js.dart:28849: List<SpeechSynthesisVoice> getVoices() {
sdk/lib/html/dart2js/html_dart2js.dart:29355: List<CssStyleValue> getAll(String property) native;
sdk/lib/html/dart2js/html_dart2js.dart:29357: List<String> getProperties() native;
sdk/lib/html/dart2js/html_dart2js.dart:29521: List<TableSectionElement> get tBodies =>
sdk/lib/html/dart2js/html_dart2js.dart:29629: List<TableCellElement> get cells =>
sdk/lib/html/dart2js/html_dart2js.dart:29831: List<Node> getDestinationInsertionPoints() native;
sdk/lib/html/dart2js/html_dart2js.dart:29887: List<Node>? get labels native;
sdk/lib/html/dart2js/html_dart2js.dart:31033: List<String> getAll(String name) native;
sdk/lib/html/dart2js/html_dart2js.dart:31183: List<Map> getLayers() native;
sdk/lib/html/dart2js/html_dart2js.dart:31187: Future requestPresent(List<Map> layers) =>
sdk/lib/html/dart2js/html_dart2js.dart:31394: List<VRStageBoundsPoint>? get geometry native;
sdk/lib/html/dart2js/html_dart2js.dart:33028: List<CssRule> getMatchedCssRules(Element? element, String? pseudoElement)
sdk/lib/html/dart2js/html_dart2js.dart:34055: List<PerformanceEntry> getEntries() native;
sdk/lib/html/dart2js/html_dart2js.dart:34057: List<PerformanceEntry> getEntriesByName(String name, String? entryType)
sdk/lib/html/dart2js/html_dart2js.dart:34060: List<PerformanceEntry> getEntriesByType(String entryType) native;
sdk/lib/html/dart2js/html_dart2js.dart:39860: FixedSizeListIterator(List<T> array)
sdk/lib/html/dart2js/html_dart2js.dart:39970: void table([Object? tabularData, List<String>? properties]) =>
sdk/lib/html/dart2js/html_dart2js.dart:40591: List<EventTarget> composedPath() => wrapped.composedPath();
sdk/lib/html/dart2js/html_dart2js.dart:40620: List<Node> get path => wrapped.path as List<Node>;
sdk/lib/html/html_common/conversions.dart:83: List newJsList(length);
sdk/lib/html/html_common/conversions.dart:156: List copyList(List e, int slot) {
sdk/lib/html/html_common/conversions.dart:221: List newDartList(length);
sdk/lib/html/html_common/conversions_dart2js.dart:78:List convertDartToNative_StringArray(List<String> input) {
sdk/lib/html/html_common/conversions_dart2js.dart:123: List newJsList(length) => JS('JSExtendableArray', 'new Array(#)', length);
sdk/lib/html/html_common/conversions_dart2js.dart:124: List newDartList(length) => newJsList(length);
sdk/lib/html/html_common/css_class_set.dart:190: List<String> toList({bool growable = true}) =>
sdk/lib/html/html_common/lists.dart:13: static int indexOf(List a, Object element, int startIndex, int endIndex) {
sdk/lib/html/html_common/lists.dart:33: static int lastIndexOf(List a, Object element, int startIndex) {
sdk/lib/html/html_common/lists.dart:55: static List getRange(List a, int start, int end, List accumulator) {
sdk/lib/html/html_common/lists.dart:70: List<Node> get rawList;
sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart:337: Transaction transactionList(List<String> storeNames, String mode) {
sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart:400: List<String>? get objectStoreNames native;
sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart:875: List<String>? get indexNames native;
sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart:1232: List<String>? get objectStoreNames native;
sdk/lib/internal/bytes_builder.dart:37: void add(List<int> bytes);
sdk/lib/internal/bytes_builder.dart:89: void add(List<int> bytes) {
sdk/lib/internal/bytes_builder.dart:181: void add(List<int> bytes) {
sdk/lib/internal/cast.dart:176: List<R> cast<R>() => new CastList<S, R>(_source);
sdk/lib/internal/iterable.dart:223: List<E> toList({bool growable = true}) =>
sdk/lib/internal/iterable.dart:314: List<E> toList({bool growable = true}) {
sdk/lib/internal/iterable.dart:782: List<E> toList({bool growable = true}) => List<E>.empty(growable: growable);
sdk/lib/internal/sort.dart:32: static void sort<E>(List<E> a, int compare(E a, E b)) {
sdk/lib/internal/sort.dart:45: static void sortRange<E>(List<E> a, int from, int to, int compare(E a, E b)) {
sdk/lib/io/common.dart:115: List<int> buffer;
sdk/lib/io/data_transformer.dart:304: List<int> convert(List<int> bytes) {
sdk/lib/io/data_transformer.dart:362: List<int> convert(List<int> bytes) {
sdk/lib/io/data_transformer.dart:414: void process(List<int> data, int start, int end);
sdk/lib/io/data_transformer.dart:425: List<int>? processed({bool flush = true, bool end = false});
sdk/lib/io/data_transformer.dart:443: void add(List<int> chunk) {
sdk/lib/io/data_transformer.dart:447: void addSlice(List<int> chunk, int start, int end, bool isLast) {
sdk/lib/io/data_transformer.dart:493: void add(List<int> data) {
sdk/lib/io/data_transformer.dart:497: void addSlice(List<int> data, int start, int end, bool isLast) {
sdk/lib/io/directory.dart:372: List<FileSystemEntity> listSync(
sdk/lib/io/directory_impl.dart:222: List<FileSystemEntity> listSync(
sdk/lib/io/directory_impl.dart:397: void error(List<Object?> message) {
sdk/lib/io/file.dart:613: List<String> readAsLinesSync({Encoding encoding = utf8});
sdk/lib/io/file.dart:632: Future<File> writeAsBytes(List<int> bytes,
sdk/lib/io/file.dart:652: void writeAsBytesSync(List<int> bytes,
sdk/lib/io/file.dart:778: Future<int> readInto(List<int> buffer, [int start = 0, int? end]);
sdk/lib/io/file.dart:793: int readIntoSync(List<int> buffer, [int start = 0, int? end]);
sdk/lib/io/file.dart:818: Future<RandomAccessFile> writeFrom(List<int> buffer,
sdk/lib/io/file.dart:830: void writeFromSync(List<int> buffer, [int start = 0, int? end]);
sdk/lib/io/file_impl.dart:629: List<String> readAsLinesSync({Encoding encoding = utf8}) =>
sdk/lib/io/file_impl.dart:632: Future<File> writeAsBytes(List<int> bytes,
sdk/lib/io/file_impl.dart:642: void writeAsBytesSync(List<int> bytes,
sdk/lib/io/file_impl.dart:694: readInto(List<int> buffer, int start, int? end);
sdk/lib/io/file_impl.dart:696: writeFrom(List<int> buffer, int start, int? end);
sdk/lib/io/file_impl.dart:806: Future<int> readInto(List<int> buffer, [int start = 0, int? end]) {
sdk/lib/io/file_impl.dart:825: int readIntoSync(List<int> buffer, [int start = 0, int? end]) {
sdk/lib/io/file_impl.dart:863: Future<RandomAccessFile> writeFrom(List<int> buffer,
sdk/lib/io/file_impl.dart:891: void writeFromSync(List<int> buffer, [int start = 0, int? end]) {
sdk/lib/io/io_sink.dart:58: void add(List<int> data);
sdk/lib/io/secure_socket.dart:796: int write(List<int> data, [int offset = 0, int? bytes]) {
sdk/lib/io/secure_socket.dart:823: int sendMessage(List<SocketControlMessage> controlMessages, List<int> data,
sdk/lib/io/secure_socket.dart:1222: List<int>? data;
sdk/lib/io/secure_socket.dart:1290: int write(List<int> inputData, int offset, int bytes) {
sdk/lib/io/secure_socket.dart:1307: int writeFromSource(List<int>? getData(int requested)) {
sdk/lib/io/secure_socket.dart:1365: List<_ExternalBuffer>? get buffers;
sdk/lib/io/security_context.dart:96: void usePrivateKeyBytes(List<int> keyBytes, {String? password});
sdk/lib/io/security_context.dart:123: void setTrustedCertificatesBytes(List<int> certBytes, {String? password});
sdk/lib/io/security_context.dart:147: void useCertificateChainBytes(List<int> chainBytes, {String? password});
sdk/lib/io/security_context.dart:170: void setClientAuthoritiesBytes(List<int> authCertBytes, {String? password});
sdk/lib/io/security_context.dart:187: void setAlpnProtocols(List<String> protocols, bool isServer);
sdk/lib/io/socket.dart:177: List<InternetAddress> get addresses;
sdk/lib/io/socket.dart:674: int write(List<int> buffer, [int offset = 0, int? count]);
sdk/lib/io/socket.dart:704: int sendMessage(List<SocketControlMessage> controlMessages, List<int> data,
sdk/lib/io/socket.dart:1040: List<ResourceHandle> extractHandles();
sdk/lib/io/socket.dart:1234: int send(List<int> buffer, InternetAddress address, int port);
sdk/lib/io/stdio.dart:448: void add(List<int> data) {
sdk/lib/io/string_transformer.dart:26: List<int> encode(String input) => encoder.convert(input);
sdk/lib/io/string_transformer.dart:27: String decode(List<int> encoded) => decoder.convert(encoded);
sdk/lib/io/string_transformer.dart:49: List<int> convert(String input) {
sdk/lib/io/string_transformer.dart:97: String convert(List<int> input) {
sdk/lib/io/string_transformer.dart:121: void add(List<int> bytes) {
sdk/lib/io/sync_socket.dart:48: int readIntoSync(List<int> buffer, [int start = 0, int? end]);
sdk/lib/io/sync_socket.dart:56: List<int>? readSync(int bytes);
sdk/lib/io/sync_socket.dart:73: void writeFromSync(List<int> buffer, [int start = 0, int? end]);
sdk/lib/isolate/isolate.dart:1050: external factory TransferableTypedData.fromList(List<TypedData> list);
sdk/lib/js/js.dart:175: external dynamic apply(List args, {thisArg});
sdk/lib/js_util/js_util.dart:54:external T callMethod<T>(Object o, Object method, List<Object?> args);
sdk/lib/js_util/js_util.dart:62:external T callConstructor<T>(Object constr, List<Object?>? arguments);
sdk/lib/mirrors/mirrors.dart:373: List<InstanceMirror> get metadata;
sdk/lib/mirrors/mirrors.dart:410: InstanceMirror invoke(Symbol memberName, List<dynamic> positionalArguments,
sdk/lib/mirrors/mirrors.dart:601: InstanceMirror apply(List<dynamic> positionalArguments,
sdk/lib/mirrors/mirrors.dart:639: List<LibraryDependencyMirror> get libraryDependencies;
sdk/lib/mirrors/mirrors.dart:667: List<CombinatorMirror> get combinators;
sdk/lib/mirrors/mirrors.dart:672: List<InstanceMirror> get metadata;
sdk/lib/mirrors/mirrors.dart:683: List<Symbol> get identifiers;
sdk/lib/mirrors/mirrors.dart:720: List<TypeVariableMirror> get typeVariables;
sdk/lib/mirrors/mirrors.dart:735: List<TypeMirror> get typeArguments;
sdk/lib/mirrors/mirrors.dart:790: List<ClassMirror> get superinterfaces;
sdk/lib/mirrors/mirrors.dart:916: List<ParameterMirror> get parameters;
sdk/lib/mirrors/mirrors.dart:988: List<ParameterMirror> get parameters;
sdk/lib/svg/dart2js/svg_dart2js.dart:3021: List<Element> get children => new FilteredElementList(this);
sdk/lib/svg/dart2js/svg_dart2js.dart:3023: set children(List<Element> value) {
sdk/lib/svg/dart2js/svg_dart2js.dart:3518: List<Node> getEnclosureList(Rect rect, SvgElement? referenceElement) native;
sdk/lib/svg/dart2js/svg_dart2js.dart:3522: List<Node> getIntersectionList(Rect rect, SvgElement? referenceElement)
sdk/lib/typed_data/typed_data.dart:372: List<int> operator +(List<int> other);
sdk/lib/typed_data/typed_data.dart:382: List<double> operator +(List<double> other);
sdk/lib/typed_data/typed_data.dart:753: external factory Int8List.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:870: external factory Uint8List.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:940: List<int> operator +(List<int> other);
sdk/lib/typed_data/typed_data.dart:994: external factory Uint8ClampedList.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:1115: external factory Int16List.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:1244: external factory Uint16List.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:1374: external factory Int32List.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:1503: external factory Uint32List.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:1633: external factory Int64List.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:1762: external factory Uint64List.fromList(List<int> elements);
sdk/lib/typed_data/typed_data.dart:1893: external factory Float32List.fromList(List<double> elements);
sdk/lib/typed_data/typed_data.dart:2016: external factory Float64List.fromList(List<double> elements);
sdk/lib/typed_data/typed_data.dart:2139: external factory Float32x4List.fromList(List<Float32x4> elements);
sdk/lib/typed_data/typed_data.dart:2218: List<Float32x4> operator +(List<Float32x4> other);
sdk/lib/typed_data/typed_data.dart:2270: external factory Int32x4List.fromList(List<Int32x4> elements);
sdk/lib/typed_data/typed_data.dart:2349: List<Int32x4> operator +(List<Int32x4> other);
sdk/lib/typed_data/typed_data.dart:2405: external factory Float64x2List.fromList(List<Float64x2> elements);
sdk/lib/typed_data/typed_data.dart:2411: List<Float64x2> operator +(List<Float64x2> other);
sdk/lib/vmservice/message.dart:256:external bool sendIsolateServiceMessage(SendPort sp, List<Object?> m);
sdk/lib/vmservice/message.dart:259:external void sendRootServiceMessage(List<Object?> m);
sdk/lib/vmservice/message.dart:262:external void sendObjectRootServiceMessage(List<Object?> m);
sdk/lib/vmservice/vmservice.dart:145:typedef Future<void> WriteFileCallback(Uri path, List<int> bytes);
sdk/lib/web_audio/dart2js/web_audio_dart2js.dart:437: AudioParam setValueCurveAtTime(List<num> values, num time, num duration)
sdk/lib/web_audio/dart2js/web_audio_dart2js.dart:706: IirFilterNode createIirFilter(List<num> feedForward, List<num> feedBack)
sdk/lib/web_audio/dart2js/web_audio_dart2js.dart:721: PeriodicWave createPeriodicWave(List<num> real, List<num> imag,
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:373: void drawBuffersWebgl(List<int> buffers) native;
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:859: List<Shader>? getAttachedShaders(Program program) native;
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:912: List<String>? getSupportedExtensions() native;
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:1493: void drawBuffers(List<int> buffers) native;
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:1541: List<int>? getUniformIndices(Program program, List<String> uniformNames) {
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:1549: void invalidateFramebuffer(int target, List<int> attachments) native;
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:1551: void invalidateSubFramebuffer(int target, List<int> attachments, int x, int y,
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:2436: List<Shader>? getAttachedShaders(Program program) native;
sdk/lib/web_gl/dart2js/web_gl_dart2js.dart:2473: List<String>? getSupportedExtensions() native; |
Personally, I'm very much in favor of this. Obviously there's a big migration that has to happen to really make use of those new classes (Vector and Array), but we can have those classes w/o changing the core APIs (the existing public methods that use and return List) at first. MigrationThe main issue is the return type of Something that could help with this is versioned method overloads which would allow the SDK to define what method is used depending on the Dart version specified so if you're on let's say Dart 3.9 you'll get methods which return I think that these new classes should be released first, then worry about migration after it's been released for awhile. You can have new APIs use it, and the community will slowly migrate, making breaking changes to their pub.dev packages. |
Coding a little in dart I have found some challenges utilizing the dart:core collection library.
I would like to propose a way to express imutable and mutable collections:
This would solve the following problem (and many others) that I have faced:
Edit: Changed naming convention (to avoid negative modifiers)
The text was updated successfully, but these errors were encountered: