Skip to content

Commit

Permalink
Splitting proposal into two.
Browse files Browse the repository at this point in the history
Closes #14
  • Loading branch information
Ginden committed Jan 27, 2018
1 parent 43179bd commit 84795fc
Show file tree
Hide file tree
Showing 23 changed files with 33 additions and 698 deletions.
96 changes: 22 additions & 74 deletions README.md
Expand Up @@ -13,14 +13,9 @@ See [formal spec WIP](https://ginden.github.io/set-methods/).

# Motivations

* it's consistent with already familiar and *widely used* `Array` API (reduced cognitive overhead)
* easier refactoring
* certain function become generic
* reduces need to depend on [Immutable.js `Set<T>`](https://facebook.github.io/immutable-js/docs/#/Set)
* reduces boilerplate code when dealing with common use cases of `Set`
* no new syntax
* allow developers coming from other languages to use familiar APIs

# Adoption

* No npm package duplicating this proposal was found
Expand All @@ -29,19 +24,9 @@ See [formal spec WIP](https://ginden.github.io/set-methods/).

## Comparision with Immutable.js

* No static `of` and `fromKeys` methods in this proposal
* No static `intersect`, `union` methods in this proposal
* `union`, `intersect`, `difference` takes single argument
* `map`, `filter`, `some`, `every`, methods are identical and follow Array API
* no `reverse`, `sort` etc. APIs inherited from `Immutable.Collection` (no sense in unordered collection) in this proposal
* no `flatMap`, `filterNot` etc. APIs not found in Array API in this proposal
* No `Set.isSet`

## Comparison with Collection.js

* Naming (`addEach` vs. `addAll`, `union` vs. `concat` etc.)
* `some`, `filter`, `every`, `map` etc. are identical and follow Array API
* many methods from Collection.js are not present in this proposal (some of them are related to observing collection feature)

## Comparison with other languages

Expand All @@ -51,20 +36,13 @@ Java `Set` interface is rather limited and doesn't include APIs found in this pr

Though, Java 8 introduces [stream API](http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html) that allow to deal with arbitrary collections.

Stream API has methods from this proposal like `map`, `filter`, `union` (as `concat`), `find` (as `findFirst`).

Stream API nor `Set` does not include `intersect`, `xor`, `some`, `every`.


### C# HashSet
Stream API has methods from this proposal like `union` (as `concat`).

Most of APIs included in this proposal are present in [C# `HashSet`](https://msdn.microsoft.com/en-us/library/bb359438.aspx)

* `intersect`, `union` (as `Concat`), `difference `, `map`, `filter` (as `Where`), `some`, `every`, `filter`, `xor` (as `SymmetricExceptWith`) are present
* Other methods outside of scope of this proposal are present (coming from `System.Linq.Enumerable` mostly)
Stream API nor `Set` does not include `intersect`, `xor`.

### Other languages

* [C# `HashSet`](https://msdn.microsoft.com/en-us/library/bb359438.aspx)
* [F# - Collections.Set](https://msdn.microsoft.com/en-au/vstudio/ee340244(v=vs.89))
* [Haskell - Data.Set](http://hackage.haskell.org/package/containers-0.5.10.2/docs/Data-Set.html)
* [Python - set/frozenset](https://docs.python.org/3.6/library/stdtypes.html#set)
Expand All @@ -91,66 +69,36 @@ Signature of these functions isn't obvious. They can accept:

This proposal does not change grammar of language.

New methods are added to `Set.prototype`.

* Array-like methods. These methods replicates functionality of `Array.prototype` methods:
* `Set.prototype.filter(predicate, thisArg)`
* `Set.prototype.map(fn, thisArg)`
* `Set.prototype.find(fn, thisArg)`
* `Set.prototype.reduce(fn, initialValue)`
* `Set.prototype.join(separator)`
* `Set.prototype.some(predicate, thisArg)`
* `Set.prototype.every(predicate, thisArg)`
* Set theory methods:
New methods based on set theory are added to `Set.prototype`.

* `Set.prototype.intersect(iterable)` - method creates new `Set` instance by set intersect operation.
* `Set.prototype.union(iterable)` - method creates new `Set` instance by set union operation.
* Alternative name ([1](https://github.com/Ginden/set-methods/issues/12#issuecomment-357887331)): `.concat`
* `Set.prototype.difference(iterable)` - method creates new `Set` without elements present in `iterable`.
* `Set.prototype.symmetricDifference(iterable)` - returns `Set` of elements found only in either `this` or in `iterable`.
* Alternative name: `.xor`
* New methods:
* `Set.prototype.addAll(...elements)` - similar to `Array.prototype.push`. Adds all of arguments to existing `Set`.
* Alternative name: `.addEach`
* `Set.prototype.deleteAll(...elements)` - reverse of `addAll`. Remove every `element` in `elements` from existing `Set`.
* Alternative names: `.deleteEach`


## Rejected Array methods

* `fill` - idea of "filling" set doesn't make sense
* `findIndex`, `indexOf` - sets aren't indexed
* `includes` - already covered by native `.has`
* `shift`, `unshift`, `pop`, `push` - sets don't have idea of "last element" or "first element"
* `reduceRight` method - iteration order for Set should be thought as implementation detail. `reduceRight` explicitly starts from "last element" - but there is no last element in set.
* `sort` - sets are unordered



## Not included in this proposal but worth considering

* `Set.prototype.isSubsetOf(otherSet)`
* `Set.prototype.isSupersetOf(iterable)`
* `Set.prototype.flatMap`, `Set.prototype.flatten` - should be added if [`Array.prototype.flatMap`](https://github.com/tc39/proposal-flatMap) is added to language
* Static `Set.union(...iterables)`, `Set.intersect(...iterables)`

## Naming

# Why not `%IteratorPrototype%` methods
**Symmetric difference**

* Explicit usage of iterators is verbose
* Compare `new Set(set.entries().filter(fn))` to `set.filter(fn)`. 19 characters of boilerplate.
* Even small codebase can have hundreds occurrences of this pattern - and hundreds places to make a mistake.
Proposed names: `xor`, `symmetricDifference`, `disjointUnion`

## Alternative
**Intersection**

* Add methods to `%SetIteratorPrototype%` or even more generic `%IteratorPrototype%` and make `Set` methods to use them internally.
* Allows for better optimization for many cases (no intermediate collections)
* **Can be delayed** - `Set` methods can be changed in future to internally use `%SetIteratorPrototype%` and it's unlikely to break the web
* Code that subclass `Set` **and** redefines `@@iterator` to not use `%SetIteratorPrototype%`.
* [Protocols proposal](https://github.com/michaelficarra/proposal-first-class-protocols)


```javascript
Set.prototype.map = function map(fn) {
const Ctor = SpeciesConstructor(this, Set);
const iterator = this.entries().map(fn);
return new Ctor(iterator);
}
```
Proposed names: `intersect`, `intersection`.

**Union**

Proposed names: `union`, `concat`.

**Difference**

Proposed names: `difference`, `minus`, `except`, `without`, `withoutAll`, `relativeComplement`.

Issues related: #2 #7 #10
4 changes: 2 additions & 2 deletions docs/ecmarkup.css
Expand Up @@ -130,11 +130,11 @@ emu-note > div.note-contents {
flex-shrink: 1;
}

emu-note > div.note-contents > p:first-of-type {
emu-note > div.note-contents > p:first-child {
margin-top: 0;
}

emu-note > div.note-contents > p:last-of-type {
emu-note > div.note-contents > p:last-child {
margin-bottom: 0;
}

Expand Down

0 comments on commit 84795fc

Please sign in to comment.