<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body text="#000000" bgcolor="#ffffff">
    On 11.07.2011 16:49, David Bruant wrote:
    <blockquote cite="mid:4E1AF156.1070401@labri.fr" type="cite">
      <meta content="text/html; charset=ISO-8859-1"
        http-equiv="Content-Type">
      Le 11/07/2011 14:29, Dmitry A. Soshnikov a écrit :
      <blockquote cite="mid:4E1AEC90.1040000@gmail.com" type="cite">
        <meta content="text/html; charset=ISO-8859-1"
          http-equiv="Content-Type">
        On 11.07.2011 2:42, David Bruant wrote:
        <blockquote cite="mid:4E1A2AC8.5000401@labri.fr" type="cite">
          <meta content="text/html; charset=ISO-8859-1"
            http-equiv="Content-Type">
          Le 10/07/2011 22:46, Dmitry A. Soshnikov a écrit :
          <blockquote cite="mid:4E1A0F8A.9070206@gmail.com" type="cite">
            <meta http-equiv="content-type" content="text/html;
              charset=ISO-8859-1">
            Here I put some extensions for arrays standard library
            (separated from this thread: <a moz-do-not-send="true"
              class="moz-txt-link-freetext"
href="https://mail.mozilla.org/pipermail/es-discuss/2011-July/015856.html">https://mail.mozilla.org/pipermail/es-discuss/2011-July/015856.html</a>
            where Array.of and Array.from were considered).<br>
            <br>
            We can consider also the following (as a first step):<br>
            <br>
            <b>- Array.prototype.remove(value, all)</b><br>
            <br>
            [1, 2, 3, 2].remove(2); // [1, 3, 2]<br>
            [1, 2, 3, 2].remove(2, true); // [1, 3]<br>
            <br>
            (seems this function is required more than Array.of, because
            at least I saw it implemented in all frameworks and used it
            myself).<br>
            <br>
            <b>- Array.prototype.subtract(array)</b><br>
            <br>
            [1, 2, 3, 4].subtract([2, 4]); // [1, 3]<br>
            <br>
            <b>- Array.seq(from, to)</b> // or Array.range(from, to)<br>
            <br>
            Array.seq(1, 5); // [1, 2, 3, 4, 5]<br>
            <br>
            <b>- Array.build(n, fn)</b><br>
            <br>
            Array.build(5, function(index) index + 1); // [1, 2, 3, 4,
            5]  <br>
            <br>
            <b>- Array.min(array), Array.max(array)</b> (can be
            implemented with Math.max/min and apply though)<br>
            <br>
            Array.min = (array) -> Math.min.apply(Math, array)<br>
            <br>
            <b>- Array.prototype.split(n)</b><br>
            <br>
            ["a", "b", "c", "d", "e"].split(3) // [["a", "b", "c"],
            ["d", "e", "f"]]<br>
            <br>
            Perhaps even to build objects from lists of keys and values
            (this function is usually called as `zip`):<br>
            <br>
            <b>- Object.fromArrays(["a", "b", "c"], [1, 2, 3]);</b> //
            {a: 1, b: 2, c: 3}<br>
            <br>
            <b>- Array.prototype.unique</b><br>
            <br>
            [1, 3, 2, 5, 5, 3].unique(); // [1, 3, 2, 5]<br>
            <br>
            Thus, all names of methods can be discussed.<br>
          </blockquote>
          I like a lot all of these ideas, but I can't help thinking
          that they do not seem to be aligned with the initial
          ECMAScript array design which is that arrays are ECMAScript
          objects (which is very different from what we'd understand of
          "array" in C or "lists" in Erlang as you cite them).<br>
          The question I ask for each of your Array.prototype ideas is
          "how does it apply to non-dense arrays?".<br>
          <br>
        </blockquote>
        <br>
        Yes, there is a difference in implementation, but ideologically
        all these concepts (C's array, JS array, List, etc) stand
        nearly. E.g. Python's lists are similar to JS arrays. Abstract
        operations are completely OK -- regardless the implementation
        and terminology.<br>
        <br>
        About the question on sparse (non-dense) arrays -- the answer is
        -- the same as array methods (e.g. map, forEach, etc) currently
        do when meat holes -- just skip them.<br>
        <br>
        E.g. for "remove" method:<br>
        <br>
        Object.defineProperty(Array.prototype, "remove", {<br>
            value: function (item, all) {<br>
                for (var k = 0; k < this.length; k++) {<br>
                    if (!(k in this)) continue; // support sparse arrays<br>
                    if (this[k] === item) {<br>
                        this.splice(k, 1);<br>
                        if (!all) break;<br>
                    }<br>
                }<br>
                return this;<br>
            },<br>
            configurable: true,<br>
            writable: true<br>
        });<br>
        <br>
        console.log([1, 2, 3, 4, 2].remove(2)); // [1, 3, 4, 2]<br>
        console.log([1, 2, 3, 4, 2].remove(2, true)); // [1, 3, 4]<br>
        <br>
        // sparse array<br>
        var data = Array(5);<br>
        data[3] = 2;<br>
        data[0] = 1;<br>
        console.log(data); // [1, , , 2, ]<br>
        console.log(data.remove(2)); // [1, , , ,]<br>
      </blockquote>
      So .length is kept from the initial array?<br>
      If so, then:<br>
      console.log([1, 2, 3, 4, 2].remove(2)); // [1, 3, 4, 2, ] // added
      empty element<br>
      <br>
    </blockquote>
    <br>
    No, the length is modified in this particular case by removing the
    items. I missed in output in first case, should be [1, , , , 2, ]
    and then [1, , , ,]. I.e. just 2 is removed, and length is
    decremented, all other positions are kept.<br>
    <br>
    <blockquote cite="mid:4E1AF156.1070401@labri.fr" type="cite"> <br>
      <blockquote cite="mid:4E1AEC90.1040000@gmail.com" type="cite"> <br>
        <blockquote cite="mid:4E1A2AC8.5000401@labri.fr" type="cite">
          Creating a List or a DenseArray (or both?) type sounds to
          better capture your intentions (especially since you provided
          a link to Erlang "list" methods).</blockquote>
        <br>
        I still don't see a big issue with handling sparse arrays as
        shown above. It's in JS array's nature to be either sparse or
        dense (regardless implementations of course -- for example,
        SpiderMonkey may create even a real low-level C's array for this
        -- [1, 2, 3], but not JS object -- it's dense and contains only
        numbers -- why not to allocate C's array -- SM does it).<br>
        <br>
        <blockquote cite="mid:4E1A2AC8.5000401@labri.fr" type="cite"> It
          could inherit everything from Array.prototype for free.<br>
          Actually, this could be implemented with proxies :-)<br>
          <br>
        </blockquote>
        <br>
        Sure, but we need the case for this. Actually we have already
        ideas in this direction -- typed arrays, which are effectively
        dense.<br>
      </blockquote>
      The idea of creating a non-sparse array type is indeed in between
      the additions of high-level abstractions (maps and sets) and what
      is done in typed arrays which are dense by nature.<br>
      <br>
      <br>
      <blockquote cite="mid:4E1AEC90.1040000@gmail.com" type="cite"> <br>
        <blockquote cite="mid:4E1A2AC8.5000401@labri.fr" type="cite">
          Since we're suggesting array additions, I would be interested
          in trying to address one issue of forEach, map, every, some
          and filter.<br>
          They all have a well-defined algorithm. Consequently, if the
          callback function has side-effects, these are deterministic.
          This, however, prevent efficient (parallelized, for instance)
          implementation. This is unfortunate since in a lot of cases,
          people don't do side-effect and would certainly trade the
          side-effect determinism guarantee for performance.<br>
          Could it be considered to add non-deterministic versions of
          these functions? They would be defined like
          Array.prototype.sort is, in terms of guarantees (like "the
          callback function will be called at most once on which array
          element" for 'every' and 'some' for instance) rather than with
          an algorithm.<br>
          I have no strong opinion on how to name them. Maybe adding an
          N (for "Non-deterministic") at the end of the equivalent
          method (Array.prototype.forEachN, Array.prototype.mapN, etc.)?<br>
          <br>
        </blockquote>
        <br>
        We can think on it, though of course a real usage use-cases are
        required for it. Currently I can say that algorithms of map,
        forEach, etc are quite logical and how they should be. Do you
        propose not to check e.g. holes and handle them too?</blockquote>
      Sorry for the confusion, my point was not about holes at all. I'm
      not concerned by holes but by the fact that current forEach, map,
      etc. spec is in term of algorithms.<br>
      When I write [1, 2, 3, 4].map(function(e){return e*e;}), I do not
      care of the order in which elements of the new array are created
      (the relative index order of function calls). However, if engines
      implemented non-deterministic .map method, I could notice it with
      the side effects if my callback function has some, which would
      make programming unpredictable, etc. As a consequence, the map
      spec had to be a deterministic algorithm.<br>
      My point is that the map spec is a deterministic algorithm because
      side-effects would be noticeable otherwise. However, this prevent
      implementations where function calls would be done in parallel for
      instance (for better performances). In some cases (like the one I
      showed), the exact order in which the function calls are performed
      does not matter, but I have no way to tell the JS engine "I don't
      need the execution order guarantee", allowing it to do the calls
      in parallel. The addition of the functions I suggested would be
      the way to say it.<br>
      <br>
    </blockquote>
    <br>
    I see, so this is for sort-of parallel "map-reduce" requests to be
    able handle an array in parallel? Yes, perhaps, though, it's even
    different separate topic to discuss. These array-method additions
    something simpler than parallel processing with non-determined
    behavior ;)<br>
    <br>
    Dmitry.<br>
    <br>
    <blockquote cite="mid:4E1AF156.1070401@labri.fr" type="cite"> <br>
      <blockquote cite="mid:4E1AEC90.1040000@gmail.com" type="cite">Or
        to handle elements which were added/removed during the
        enumeration?</blockquote>
      Non-deterministic too.<br>
      <br>
      <blockquote cite="mid:4E1AEC90.1040000@gmail.com" type="cite">Or
        how the non-determinism looks like here?<br>
      </blockquote>
      faster :-)<br>
      Of course, that's a trade-off between determinism and (potential)
      performance. The person who'd use forEachN would need to
      acknowledge the risk of non-determinism.<br>
      <br>
      David<br>
    </blockquote>
    <br>
  </body>
</html>