Array generation

Brendan Eich brendan at mozilla.com
Sun Jul 10 16:24:51 PDT 2011


>>> range.__doc__
'range([start,] stop[, step]) -> range object\n\nReturns a virtual sequence of numbers from start to stop by step.'
>>> [i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [i for i in range(10, 20)]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [i for i in range(10, 20, 2)]
[10, 12, 14, 16, 18]

It seems to me we want

* range(end), range(start, end), range(start, end, step) as in Python 3, a generator.

  function range(...args) {
    const start = (args.length == 1) ? 0 : Number.toInteger(args[0]);
    const end = Number.toInteger((args.length > 1) ? args[1] : args[0]);
    const step = (args.length > 2) ? Number.toInteger(args[2]) : 1;

    if (Number.isNaN(start) || Number.isNaN(end) || Number.isNaN(step)) {
      throw new TypeError("...");
    }

    for (let i = start; i != end; i += step) {
      yield i;
    }
  }

* a way to take an iterator I and exhaust it to build an array: [x for x of I] is the comprehension form (note the paren-free for-of head). A functional form per Allen's principle would be helpful some of the time: Array.fromIterator or Array.exhaust?

* a standard array element-key-only-and-as-integral-index (*not* string) and elements-only iterators: for i of indexes(array), for v of elements(array).

See http://wiki.ecmascript.org/doku.php?id=harmony:iterators for more on for-of.

/be

On Jul 10, 2011, at 1:52 PM, Rick Waldron wrote:

> David, I like the way you paint your bike sheds. Array.range() (or similarly functional but differently named) is definitely another one of those "oft-rerolled" solutions.
> 
> Rick
> 
> On Sun, Jul 10, 2011 at 4:23 PM, David Herman <dherman at mozilla.com> wrote:
> > So from this viewpoint (and regarding that example with squares), it's good to have also `Array.seq(from, to)` method (the name is taken from Erlang, I just frequently uses lists:seq(from, to) there):
> 
> <bikeshed>Array.range seems like an intuitive name as well.</bikeshed>
> 
> > Array.seq(1, 5).map((x) -> x * x); [1, 4, 9, 16, 25]
> 
> This pattern (integer range immediately followed by map) is so common that many Schemes have a more general function that fuses the two traversals, sometimes called build-list or list-tabulate:
> 
>    Array.build(n, f) ~~~ [f(0), ..., f(n-1)]
> 
> Another common and useful fusion of two traversals that's in many Schemes is map-filter or filter-map:
> 
>    a.filterMap(f) ~~~ [res for [i,x] of items(a) let (res = f(x, i)) if (res !== void 0)]
> 
> I rather arbitrarily chose to accept both null and undefined here as way to say "no element" -- a reasonable alternative would be to accept *only* undefined as "no element".
> 
> Dave
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110710/7cbefd87/attachment.html>


More information about the es-discuss mailing list