Skip to content

Object Spread operator #3449

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

Open
TekExplorer opened this issue Nov 7, 2023 · 3 comments
Open

Object Spread operator #3449

TekExplorer opened this issue Nov 7, 2023 · 3 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@TekExplorer
Copy link

Consider adding a spread operator to classes.
This could be useful for objects from fast_immutable_collections which dont implement Map/List/Set

class SomeClass {
  String get foo => 'foo';
  int get bar => 10;
  
  List<dynamic> operator ...[] => [foo, bar];
  Map<String, dynamic> operator ...{} => {'foo': foo, 'bar': bar};

  // for record spreading, if added (not a parameter list - acts like a getter. maybe a different distinction system?)
  ({String foo, int bar}) operator ...() => (foo: foo, bar: bar);
}

// {'foo1': 'foo2', 'foo': 'foo', 'bar': 10, 'bar1': 420}
final map = {
   'foo1': 'foo2',
  ...SomeClass(),
  'bar1': 420,
};
// ['foo1', 'foo', 10 , 420]
final iterable = [
   'foo1',
  ...SomeClass(),
   420,
];

// (10, 'bar', foo: 'foo', bar: 10, foo1: 'bar2')
// of static type (int, String, {String foo, int bar, String foo1})
final record = (
   10,
   ...SomeClass(),
   'bar',
   foo1: 'bar2',
);

// perhaps in the future
void fn({required String foo, required int bar}) {}
void invoke() => fn(...SomeClass());

Spread operators would reclusively call until a valid spreadable appears
classes like Map, Iterable, (and maybe Record) could have an external operator ...[]|{}|() which actually spreads the values
ex:

class IList<T> /* doesnt implement list */ {
  // whatever
 List<T> _internalList;

 List<T> operator ...[] => _internalList;
}

final iList = IList(['one', 'two']);
final List<String> list = [...iList];

related #3448 #1293

@TekExplorer TekExplorer added the feature Proposed language feature that solves one or more problems label Nov 7, 2023
@TekExplorer
Copy link
Author

The record version probably needs record subtyping to allow sub classes to override it to add more parameters...
That one can probably be held off on for now

@lrhn
Copy link
Member

lrhn commented Nov 7, 2023

Seems wasteful to create a list, just to immediately throw it away again after spreading.

Instead of introducing a specialized operator that can only be invoked inside specific contexts, how about just making it a getter or function:

  List<dynamic> get asList=> [foo, bar];
  Map<String, dynamic> get asMap => {'foo': foo, 'bar': bar};

and spread it as:

final map = {
   'foo1': 'foo2',
  ...SomeClass().asMap,
  'bar1': 420,
};

(Coding style says to make such asX members into functions instead of getters, though.)

Or to put it shortly: don't be an Iterable, have an Iterable. Favor composition over inheritance.
(Or admit to being an Iterable, rather than having an operator that implicitly converts the object to an Iterable, and which only works for spreading. Why not also for/in iteration?)

@TekExplorer
Copy link
Author

Using fic as an example, I am able to spread an IList just fine because we can implement Iterable, and that's great.

ISet too I assume, since it should be the same.

However, we can't spread IMap since there's no non-mutable interface.

Perhaps it could be more useful to ask for some kind of MapSpreadable interface for this particular usage?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

2 participants