Giter VIP home page Giter VIP logo

ecmascript-iterator-hof's Introduction

Higher Order Functions on Iterators.

Stage: 0, Strawman

Author: Lee Byron

Note: This proposal is still very much a work in progress and has not yet been formally proposed.

Providing common higher order function utilities to all Iterators, via the Adaptor pattern.

This proposes introducing a new global function, Iterator which performs the adaptor pattern.

var myArray = [ 1, 2, 3 ]
var myIter = Iterator(myArray)
myIter instanceof Iterator // true
myIter.next() // { value: 1, done: false }

This provides a nicer alternative to myArray[Symbol.iterator]() for accessing the default iterator for any iterable collection (including Map and Set), provides a clearer way to access %IteratorPrototype% (via Iterator.prototype), and via the adaptor pattern ensures the returned result has %IteratorPrototype% in its prototype chain.

And if the returned result is always Iterator(input) instanceof Iterator, then adding higher-order methods to %IteratorPrototype% enables familiar collection methods on all iterators.

This proposal suggests adding the following methods to %IteratorPrototype%:

  • concat
  • includes
  • every
  • filter
  • find
  • findIndex
  • flatten
  • forEach
  • join
  • indexOf
  • map
  • reduce
  • scan
  • slice
  • some
  • tee
  • zip

These should mostly look familiar, they're almost all borrowed from the ES5 additions to Array.prototype, most of which originally proposed in Array#extras. There are a few similarities and differences and a couple new methods:

callbackFn still take three args.

Most higher order methods on Array.prototype accept callbackFn of the arity:

function (value, index, collection) {...}

Iterator higher order methods accept the same function signature:

function (value, index, iterator) {...}

Where value is (usually) the value key of the iterator's next result object, index is an index starting at 0 which indicates how many times next has been called on the iterator, and iterator is the iterator being operated over (and not the collection from which it was created).

Completion values

Some iterators return "completion values", these are not affected by the higher-order-functions.

Methods on Array.prototype not added to Iterator.prototype

Array's mutative methods (push, pop, shift, unshift, sort) do not make sense in the context of Iterators and are omitted.

Since Iterators can only be iterated in one direction, all methods requiring a reversed traversal are not included:

  • reduceRight
  • lastIndexOf
  • reverse

New methods on Iterator.prototype not found on Array.prototype

flatten

This method is similar to concat, however operates on an iterable of iterables rather expecting each concatenated iterable as an argument.

var deepValues = [ [ 'A' ], [[ 'B' ]], 'C' ]
var flat = deepValues.values().flatten() // [ 'A', ['B'], 'C' ]

iterator.flatten(), like iterator.concat(), only expands those values which are Spreadable. This is determined very similarly to IsConcatSpreadable, however the last step determines if the value is Iterable rather than Array.

scan

This method returns a new Iterator resulting from calling the provided function for each value in the Iterator, using the result of the previous function as an argument in the subsequent call, much like "reduce".

tee

This method returns n independent iterators from this iterator by buffering the original iterator.

This same method can be found in Python's itertools.

zip

This method allows for multiple iterables to be "zipped" together into an iterable of Array objects. This is a fairly common higher order operation in functional languages, but is especially useful in tandem with the Map constructor which expects an iterable of [K, V] arrays.

var keys = ['A', 'B', 'C'];
var vals = ['X', 'Y', 'Z'];
var map = new Map(keys.values().zip(vals));

Testing:

node examples.js

Open Questions

  • What sort of cleanup is necessary if a HOF throws?
  • Prototypes vs method assignments
  • Test and double check all return/throw methods for appropriate behavior
  • Test and double check throwing from generator functions performs correctly
  • Can some of the throw and return impls be generalized?
  • Can we illustrate behavior of each method via generator functions?

ecmascript-iterator-hof's People

Contributors

leebyron avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

smartb2b

ecmascript-iterator-hof's Issues

Should transforms operate on "completion value"?

The new for ... of syntax ignores the completion value, so it would make sense to ignore it for the different functions introduced here.

function *example(){
 yield 1;
 yield 2;
 return 3;
}

for(let i of example()) console.log(i);

Outputs

1
2

Async Iterators

Would it make sense for this proposal to also define the same functions for Async Iterables to kill two birds with one stone?

Having higher order functions on async iterables would make async programming extremely powerful.

Is flatMap really necessary?

On can achieve the exact same effect by chaining map and flatten. When xstream (an Observable implementation) was being made, the creator, @staltz, omitted "flatMap" because [it was easier to understand]. I think this reasoning applies to higher order functions with Iterators.

Add collect method

Consider this snippet in the readme which incorrectly suggests the return value of flatten is an array.

var deepValues = [ [ 'A' ], [[ 'B' ]], 'C' ]
var flat = deepValues.values().flatten() // [ 'A', ['B'], 'C' ]

Adding the method collect:

class Iterator<T> {
    collect<R>(fn: (iterator: Iterator<T>) => R): R;
}

Would allow:

var deepValues = [ [ 'A' ], [[ 'B' ]], 'C' ]
var flat = deepValues.values().flatten().collect(Array.from) // [ 'A', ['B'], 'C' ]

Bind operator for chaining

Once you introduce a series of operators, people are bound to want to have more.
I think it would be a good idea to introduce a .bind(fn, ...args) operator which would allow chaining with custom operators without having to subclass or modify the prototype.

Spec functions as generators

Is this an opportunity to spec the functions as generators? A few examples:

class Iterator {
    *concat(...iterators) {
        yield* this;
        for (iterator in iterators) {
            yield* iterator;
        }
    }

    *map(mapFn) {
        for (value in this) {
            yield mapFn(value);
        }
    }

    *filter(filterFn) {
        for (value in this) {
            if (filterFn(value)) {
                yield value;
            }
        }
    }

    *flatten() {
        for (iterator in this) {
            yield* iterator;
        }
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.