Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Please, use a protocol instead of adding a new .toObject method. #11

Closed
zloirock opened this issue Nov 2, 2019 · 3 comments
Closed

Comments

@zloirock
Copy link
Contributor

zloirock commented Nov 2, 2019

I explained this conception here. Copy-paste:


It could look like a new proposal, but since this proposal includes Iterator.prototype.toArray method, seems, it should be opened here and, maybe, be a part of this proposal.

So, this proposal contains .toArray, by why it's limited only to arrays? Instead of adding methods for each collections type (.toObject, .toSet, etc.), we could add one: .to(Collection) and a protocol for that.

Instead of

Object.fromEntries([1, 2, 3, 4, 5]
  .map(it => it ** 2)
  .filter(it => it % 2)
  .values()
  .map(it => [`key${it}`, it]))
// => { key0: 1, key1: 9, key2: 25 }

we could use a pipeline operator:

[1, 2, 3, 4, 5]
  .map(it => it ** 2)
  .filter(it => it % 2)
  .values()
  .map(it => [`key${it}`, it])
  |> Object.fromEntries
// => { key0: 1, key1: 9, key2: 25 }

But it's mixin of different operators and readable not very good.

In my opinion, the chaining of methods could be better:

[1, 2, 3, 4, 5]
  .map(it => it ** 2)
  .filter(it => it % 2)
  .values()
  .map(it => [`key${it}`, it])
  .to(Object)
// => { key0: 1, key1: 9, key2: 25 }

Adding .toArray to this proposal is adding the same, but only for arrays, more other, we have an additional simple way of conversion to arrays - spread operator.

So, how should work .to method? It's just passing this to the method of the passed constructor, the name of this method is a part of this protocol. So, what could be used as this protocol?

  • It could be .from method.

At this moment, it's available of Array, %TypedArray%, on Observable proposal, available proposal for adding .from method to Set, Map, WeakSet, WeakMap.
But it missed at least on Object (here used .fromEntries) and URLSearchParams.

  • It could be .fromIterable method or @@fromIterable well-known symbol.

More other, since here used iterables protocol, it could be added not only to Iterator.prototype but also to prototypes of all iterables, but it's not a part of this proposal...

[1, 2, 3, 2, 1].to(Set).map(it => [`key${it}`, it]).to(Map);

So, something like that:

Symbol.fromIterable = Symbol('Symbol.fromIterable');

Iterator.prototype.to = function to(Constructor) {
  return Constructor[Symbol.fromIterable](this);
};

Array[Symbol.fromIterable] =
Observable[Symbol.fromIterable] = function (iterable) {
  return this.from(iterable);
};

Object[Symbol.fromIterable] = function (iterable) {
  return this.fromEntries(iterable);
};

Map[Symbol.fromIterable] =
Set[Symbol.fromIterable] =
WeakMap[Symbol.fromIterable] =
WeakSet[Symbol.fromIterable] =
Iterator[Symbol.fromIterable] =
Object.getPrototypeOf(Int8Array)[Symbol.fromIterable] =
URLSearchParams[Symbol.fromIterable] = function (iterable) {
  return new this(iterable);
};

// as an option
Array.prototype.to =
Map.prototype.to =
Set.prototype.to =
Object.getPrototypeOf(Int8Array).prototype.to =
URLSearchParams.prototype.to = Iterator.prototype.to;
@bergus
Copy link

bergus commented Nov 3, 2019

I agree with this, but could you please edit your post to repeat the reasoning here as well?

Prior art: Rust .collect() with the FromIterator interface, Java .collect() with the Collector interface and the vast Collectors helpers. (I'm surprised to see Scala as the odd one out here).

@decompil3d
Copy link
Member

Yes, a generic collect method was considered in the Iterator Helpers proposal but left out due to complexity. I believe the author of that proposal intends to bring a separate proposal up after Iterator Helpers is complete (hopefully) that covers this generic collect. So I'm going to forego including it here. Generally, I agree that using Object.fromEntries is reasonable; and indeed, the pipeline operator would help readability there too.

@michaelficarra
Copy link
Member

@bergus @decompil3d Following the iterator helpers work, I plan to work on a proposal for a "from iterable" (pull) or "builder" (push) protocol.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants