Flow: Handling unknown/arbitrary sized list of generics.

Created on 20 Feb 2019  路  2Comments  路  Source: facebook/flow

Proposal

Adding a way to handle lists of generics with unbounded size:

function identity<...T>(array: T) {
  // ...
}

Which would be equivalent to:

declare function identity2<A, B>(items:[A, B]): [A, B];
declare function identity2<A, B, C>(items:[A, B, C]): [A, B, C];
// with infinitely many signatures
function identity<T>(items:T): T {
    return items;
} 

Test it here.

Use case

That would for example be useful to type a reverse function. That function would take an arbitrary number of arguments and return them in reverse order: reverse(1, 2, "3") = ["3", 2, 1]. For now it seems that this is only possible by having a fixed length for the input, or by declaring several signatures, one for each possible number of arguments.

A more concrete use case I have is with this zip function, which for now only takes 2, 3 or 4 iterables as parameter:

declare function zip<A, B>(Iterable<A>, Iterable<B>): Iterable<[A, B]>;
declare function zip<A, B, C>(Iterable<A>, Iterable<B>, Iterable<C>): Iterable<[A, B, C]>;
declare function zip<A, B, C, D>(Iterable<A>, Iterable<B>, Iterable<C>, Iterable<D>): Iterable<[A, B, C, D]>;
export function *zip<T>(...iterables:Array<Iterable<T>>): Iterable<Array<T>> {
   const iterators = iterables.map(iterable => iter(iterable));
   while(true){
      const items = iterators.map(iterator => iterator.next());
      if (items.some(item => item.done)){
         return;
      }
      yield ((items.map(item => { return item.value }): Array<any>): Array<T>);
  }
}
discussion feature request

Most helpful comment

All 2 comments

Well, I think it is!

export function *iter<T>(iterable:Iterable<T>): Iterator<T> {
   yield* iterable;
}

export function *zip<T: $ReadOnlyArray<mixed>>(...iterables:Array<Iterable<T>>): Iterable<Array<T>> {
   const iterators = iterables.map(iterable => iter(iterable));
   while(true){
      const items = iterators.map(iterator => iterator.next());
      if (items.some(item => item.done)){
         return;
      }
      yield ((items.map(item => { return item.value }): Array<any>): Array<T>);
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

funtaps picture funtaps  路  3Comments

damncabbage picture damncabbage  路  3Comments

ctrlplusb picture ctrlplusb  路  3Comments

mmollaverdi picture mmollaverdi  路  3Comments

jamiebuilds picture jamiebuilds  路  3Comments