Skip to content
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

Can this be more general? #8

Open
sffc opened this issue Jul 15, 2020 · 9 comments
Open

Can this be more general? #8

sffc opened this issue Jul 15, 2020 · 9 comments
Labels
question Further information is requested

Comments

@sffc
Copy link

sffc commented Jul 15, 2020

As others have pointed out, we already have [...new Set(array)] for primitives. So, I think that the question this proposal is addressing can be generalized to, "use something other than === to find duplicate objects in a Set".

Here are a couple other potential ways to solve this problem off the top of my head (I haven't thought them through; these are just ideas):

  • [...new Set(array, { comparator: (a, b) => a.id === b.id })] -- this would set a comparator on the Set to be used for all future additions to that specific Set.
  • Object.prototype[@@setKey] -- if present on an object, [@@setKey] should be used instead of the object pointer when checking for equality in the Set.
@ljharb
Copy link
Member

ljharb commented Jul 15, 2020

https://github.com/tc39/proposal-collection-normalization seems relevant.

@hax
Copy link
Member

hax commented Jul 18, 2020

@ljharb It seems collection normalization will convert the values but unique proposal will not.

@ljharb
Copy link
Member

ljharb commented Jul 18, 2020

What i mean is, that approach could be used for a new collection hook that override the comparator (which defaults to SameValueZero)

@hax
Copy link
Member

hax commented Jul 18, 2020

Not sure how it could be used to override the comparator --- As I understand, it's not override the comparator but just change the values, so u may need a map to keep the mappings from the converted values to original values.

@ljharb
Copy link
Member

ljharb commented Jul 18, 2020

The normalization proposal can not, you’re correct. I’m suggesting the approach of “an options bag passed to the constructor that allows overriding internal algorithms”.

@hax
Copy link
Member

hax commented Jul 19, 2020

So it would be new Set(array, { comparator: (a, b) => a.id === b.id }) just as @sffc suggested? But as I understand, to make such usage efficient, very likely we finally also need write something close to hashCode. And if that, it likely we need container type or equal/hash protocol anyway, and make normalization not very useful 😅

@ljharb
Copy link
Member

ljharb commented Jul 19, 2020

I’m not sure why it wouldn’t be efficient as-is.

@TechQuery TechQuery added the question Further information is requested label Jul 28, 2020
@bergus
Copy link

bergus commented Jul 28, 2020

This is exactly what I thought when I read "new Set(array) in ECMAScript 6 isn't enough for Non-primitive values" in the readme.

@hax No, it would be Array.from(new Map(array.map(x=>[x,x]), { coerceKey: x => x.id }).values()) or hopefully Array.from(new Set(array, { coerceKey: x => x.id })). An arbitrary comparator (not even an ordering one but just an equivalence one) cannot be used for efficient lookup.

@hax
Copy link
Member

hax commented Aug 13, 2020

I’m not sure why it wouldn’t be efficient as-is.

@ljharb Because comparator could be complex (eg. deep equal).

@bergus I think we have similar thought about that. comparator by itself can't be efficient, but comparator + hashCode could. To some degree, coerceKey is like a stronger hashCode which never have collisions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants