sdk
                                
                                 sdk copied to clipboard
                                
                                    sdk copied to clipboard
                            
                            
                            
                        Dart 3 core library changes
Generally it's hard to evolve the Dart core libraries, as most changes tend to be potentially widely breaking. For example, adding a new member to a class in the core libraries can be breaking to any code that that implements that class, given all Dart classes are implicit interfaces.
While we still don't want major breaking changes in Dart 3 outside of the non-null discontinuation, we have an opportunity to be mildly breaking.
The concrete list of discussions is still under discussion.
dart:core
- 
Add Iterable.whereNotNull()as an extension to Iterable indart:core(currently inpackage:collectionas an extension)
- 
Add Iterable.firstOrNull()/Iterable.lastOrNull()/Iterable.elementAtOrNull()as extension methods to Iterable indart:core(some currently inpackage:collectionas an extension)
- 
Add DateTime.copyWith(). Long standing request. As an extension method, to avoid breakage.
Maybe add a name property to FileSystemEntity and change the firstWhere() method from Iterable to return a nullable value...
With records being a thing, we may want to embrace them.
We have a number of "indexed" iterable extensions in package:collection that would otherwise be worthy candidates for inclusion in dart:core, but with records, we can instead introduce a single "add index to iterable" operation:
extension IterableExtension<T> on Iterable<T> {
  Iterable<(int, T)> get indexed sync* {
    var index = 0;
    for (var element in this) yield (index++, element);
  }
}
Then you would be able to do:
for (var (i, e) in something.indexed) {
  print("#$i: $e");
}
(We'll be missing some affordances in the first release, for example we probably won't have patterns in parameters, so not everything will be as smooth as the for-in.)
We should consider whether there are other uses of records that afford a similar big result for a small effort.
Usually this one is mentioned as well:
extension MapExtension<K, V> on Map<K, V> {
  Iterable<(K, V)> get keyed sync* {    
    for (var element in this.entries) yield (element.key, element.value);
  }
}
// Example usage.
void main() {
  var map = {1: "one", 2: "two"};
  for (var (key, value) in map.keyed) {
    print('$key: $value');
  }
}
The Map.keyed here is mostly redundant with the existing Iterable<MapEntry<K,V>> get entries.
You can do for (var MapEntry(:key, :value) in map.entries) ... with pattern matching. If we can get rid of the redundant MapEntry too, it would be even better.
(It would be nice to make MapEntry an alias for ({K key, V value}), but that would break code currently using the constructor. I'm more inclined to make it either a struct, or make it a view on ({K key, V value}), preferently a transparent view which can be cast in either direction, if such a thing exists. Really, I just want a place to hang the constructor.)
The DateTime.copyWith extension is now merged:
https://dart-review.googlesource.com/c/sdk/+/258541
If I could ask for anything crazy in Dart 3, I would go with print("value is", a). I alwaaays struggle with Dart syntax, and it is possible to implement that without varargs. Since print is not supposed to run in release mode, the minimal performance impact is negligible.
https://github.com/dart-lang/sdk/issues/49084
Hey @lrhn can you please check the list at the top (which I updated) to see if it's complete for 3?
LGTM.