On this weblog publish, we look at the ECMAScript proposal “Set strategies for JavaScript” by Michał Wadas, Sathya Gunasekara and Kevin Gibbons. It introduces new strategies for Units.
New Set strategies that return Units
set.union(different)
This technique returns a Set that’s the union of this
and different
.
Kind signature:
Set<T>.prototype.union(different: SetReadOperations<T>): Set<T>
The kind of different
, SetReadOperations
is mentioned later. It signifies that different
supplies all operations that the brand new strategies want for his or her algorithms.
Instance:
assert.deepEqual(
new Set(['a', 'b', 'c']).union(new Set(['c', 'd'])),
new Set(['a', 'b', 'c', 'd'])
);
set.intersection(different)
This technique returns a Set that’s the intersection of this
and different
.
Kind signature:
Set<T>.prototype.intersection(different: SetReadOperations<T>): Set<T>
Instance:
assert.deepEqual(
new Set(['a', 'b', 'c']).intersection(new Set(['c', 'd'])),
new Set(['c'])
);
set.distinction(different)
This technique returns a Set that’s the distinction between this
and different
.
Kind signature:
Set<T>.prototype.distinction(different: SetReadOperations<T>): Set<T>
Instance:
assert.deepEqual(
new Set(['a', 'b', 'c']).distinction(new Set(['c', 'd'])),
new Set(['a', 'b'])
);
set.symmetricDifference(different)
This technique returns a Set that’s the symmetric distinction between this
and different
. What does that imply? These are equal definitions of the symmetric distinction:
this
−different
∪different
−this
- (
this
∪different
) − (this
∩different
) this
xordifferent
(unique OR)- All parts that solely exist in one of many two units
Kind signature:
Set<T>.prototype.symmetricDifference(different: SetReadOperations<T>): Set<T>
Instance:
assert.deepEqual(
new Set(['a', 'b', 'c']).symmetricDifference(new Set(['c', 'd'])),
new Set(['a', 'b', 'd'])
);
assert.deepEqual(
new Set(['a', 'b']).symmetricDifference(new Set(['c', 'd'])),
new Set(['a', 'c', 'b', 'd'])
);
New Set strategies that return booleans
set.isSubsetOf(different)
This technique returns true
if this
is a subset of different
and false
in any other case.
Kind signature:
Set<T>.prototype.isSubsetOf(different: SetReadOperations<T>): boolean
Instance:
assert.deepEqual(
new Set(['a', 'b', 'c']).isSubsetOf(new Set(['a', 'b'])),
false
);
assert.deepEqual(
new Set(['a', 'b']).isSubsetOf(new Set(['a', 'b', 'c'])),
true
);
set.isSupersetOf(different)
This technique returns true
if this
is a superset of different
and false
in any other case.
Kind signature:
Set<T>.prototype.isSupersetOf(different: SetReadOperations<T>): boolean
Instance:
assert.deepEqual(
new Set(['a', 'b', 'c']).isSupersetOf(new Set(['a', 'b'])),
true
);
assert.deepEqual(
new Set(['a', 'b']).isSupersetOf(new Set(['a', 'b', 'c'])),
false
);
set.isDisjointFrom(different)
This technique returns true
if this
is disjoint from different
and false
in any other case.
Kind signature:
Set<T>.prototype.isDisjointFrom(different: SetReadOperations<T>): boolean
Instance:
assert.deepEqual(
new Set(['a', 'b', 'c']).isDisjointFrom(new Set(['c', 'd'])),
false
);
assert.deepEqual(
new Set(['a', 'b', 'c']).isDisjointFrom(new Set(['x'])),
true
);
Guidelines for this
and different
For all the new Set strategies:
this
have to be an occasion ofSet
.different
should implement the interfaceSetReadOperations
proven under.- The complete interface is at all times enforced, even when a technique doesn’t use all of its strategies.
interface SetReadOperations<T> {
dimension: quantity;
has(key: T): boolean;
keys(): Iterator<T>;
}
Infinite Set-like knowledge
The .dimension
of different
may be Infinity
. Which means we are able to work with infinite Units:
const evenNumbers = {
has(elem) {
return (elem % 2) === 0;
},
dimension: Infinity,
keys() {
throw new TypeError();
}
};
assert.deepEqual(
new Set([0, 1, 2, 3]).distinction(evenNumbers),
new Set([1, 3])
);
assert.deepEqual(
new Set([0, 1, 2, 3]).intersection(evenNumbers),
new Set([0, 2])
);
Solely two strategies don’t assist different
being an infinite Set:
union
symmetricDifference
The rationales behind the API design
These are the rationales behind the API design (supply):
-
Why does
this
need to be aSet
?- TC39 might have chosen a extra versatile interface for
this
which might have enabled us to make use of the Set strategies generically. Nonetheless, not doing so makes implementations less complicated and sooner.
- TC39 might have chosen a extra versatile interface for
-
Why use an interface for
different
?- Because of the interface,
different
is usually a knowledge construction apart from a Set. It was chosen as a compromise between accepting solely Units and any iterable objects.
- Because of the interface,
-
Why is the total interface at all times enforced for
different
?- That makes the API less complicated and hides implementation particulars.
-
Why was the strategy title
.keys()
chosen for iterating over knowledge construction parts?- That’s on account of compatibility with the one Set-like knowledge construction at present in the usual library –
Map
:- The strategy key
Image.iterator
doesn’t work as a result of that Map technique returns key-value pairs. - The strategy key
'values'
doesn’t work as a result of that Map technique shouldn’t be suitable with the Map technique.has()
(which accepts keys, not values).
- The strategy key
- That’s on account of compatibility with the one Set-like knowledge construction at present in the usual library –
-
Why are the brand new technique names nouns and never verbs like
.add()
?- A tough common rule (with exceptions) is that verb strategies mutate
this
, whereas noun strategies return new knowledge – for instance:set.add()
andset.keys()
.
- A tough common rule (with exceptions) is that verb strategies mutate
Implementations
I’m conscious of the next two polyfills: