tc39 / proposal-flatMap

proposal for flatten and flatMap on arrays
https://tc39.github.io/proposal-flatMap
214 stars 19 forks source link

Self-containing arrays in `.flatten(Infinity)` #35

Closed Jamesernator closed 7 years ago

Jamesernator commented 7 years ago

Basically this issue is about what should happen in these sort've cases:

const a = []
a.push(a)

a.flatten(Infinity)

// ----
const b = []
b.push(b)
b.push(b)

b.flatten(Infinity)

// ----
const c = []
c.push([[[[[c]]]]])

c.flatten(Infinity)

Some potential options I see are:

  1. Continually flatten in an infinite loop (probably not a great idea but at least it prevents any arbitrary behavior)

  2. Throw an error if an infinite loop would be caused (requires adding every seen array to a Set and throwing if the item has already been added to that Set)

  3. Don't re-flatten things that have already been seen, the first two examples would effectively not change the list, the final example would wind up as just [c] (same Set cost as above but tries to do something rather than throwing)

ljharb commented 7 years ago

I'd vote for 2.

michaelficarra commented 7 years ago
a = b.flatten(c);

should be equivalent to

a = b;
for (let i = 0; i < c; ++i) {
  a = a.flatten();
}
ljharb commented 7 years ago

@michaelficarra in that case, that sounds like option 1?

michaelficarra commented 7 years ago

Yes.

ljharb commented 7 years ago

I think 1 or 2 is sensible; there is already a precedent for avoiding cycles when setting prototypes; but there's also lots of precedent for "letting infinite loops be infinite", so ¯\_(ツ)_/¯

bakkot commented 7 years ago

Yeah, this is a weird edge case, and I don't know that it's going to be any more common than infinite loops resulting from getters or proxies, which are cases where it is impossible to short-circuit infinite loops. So my vote is also for 1.

bakkot commented 7 years ago

Going with option 1.