Set([0, -1, 3]) .values() .filter(x => x >= 0) .map(x => x * 2) .toArray(); // Pipe operator const arr = new Set([0, -1, 3]) |> filter(x => x >= 0, %) |> map(x => x * 2, %) |> toArray(%); • All of the upsides of iterator methods, • none of the downsides
cant change of current protocol • Programmers have to know: • Does a value support the API? • How to get an iterator. • Iterator.from(value) as common pattern? • Why not a wrapping API then? • Libraries can’t add methods to API. • Consequence: mix of API styles Pros: • Chainable • Implicit namespace (no “import” needed) • Value-speci fi c implementations of operations are used automatically (override iterator method).
implementations of operations are not used automatically: • Solution 1: Use different function. • Solution 2: Delegate to symbol-keyed methods (similar: string → RegExp). • No chaining • Namespaced (must qualify or “import” via destructuring) Pros: • No need to change the existing protocol. • Same style as current built-in iteration-based mechanisms • Follow precedents such as Lodash and Ramda. • Easy to apply to operands • Same style as complementary libraries. • Keep options open w.r.t. pipe operator.
Related: Array.from() vs. Iterable.toArray(syncIterable) • Function signature style? • Main operand fi rst (OOP)? • Better for normal function calls and hack pipes • Main operand last (partial application)? • Better for .bind() • A function-based API would work well as a built-in module. In the cards?