Re: Wanted: standard Array function to append an array's elements to another array

2011-11-01 Thread David Bruant
Le 01/11/2011 22:17, David Bruant a écrit :
> (...)
>
> Regarding implementations of .push, if they can
I meant *can't*, of course.
> do as good as a .pushAll
> could, then they are just buggy and should be fixed in my opinion.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Wanted: standard Array function to append an array's elements to another array

2011-11-01 Thread David Bruant
Hi,

I have just noticed [1], read all messages on this thread and thought
that the "JavaScript stack size limit" for
Array.prototype.push.apply(firstArray, secondArray); was an
implementation concern rather than anything else and it really sounds
weird to me to add a method just because implementations aren't capable
of performing well with some methods.
Theorically speaking, why .pushAll would do better than
.push.apply+second argument? There is no reason I can think of.

I think that implementors did implement strictly ES5 definition of push:
Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] ) which considers
each item as a new argument, making the stack grow. Why would a .pushAll
do better? Because there is only one argument which is an array. So I
think that instead of adding pushAll, we'd rather redefine .push with
the great "...rest" parameters [2]

Array.prototype.push = function(...items){
let O = ToObject(this);
let lenVal = O.length;
let n = ToUint32(lenVal);
let itemsList = ToList(items); // sorry for the bickshed
while(itemsList.length != 0){
let E = itemsList.pop(); // bickshed bis
O[n] = E;
n++;
O.length = n;
}
return n;
};

(which is pretty much Jeff's implementation of .pushAll in the initial
message)

As a matter of fact, maybe that all methods that where previously
defined as "myFunction(a, b [, c1 [, c2 [ , … ] ] ])" would have rather
being re-specified in the form of "myFunction(a, b, ...c)". Should I
file a bug on that?

Regarding implementations of .push, if they can do as good as a .pushAll
could, then they are just buggy and should be fixed in my opinion.

What do you think?

David

[1] http://wiki.ecmascript.org/doku.php?id=strawman:array.prototype.pushall
[2] http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters


Le 25/07/2011 21:54, Jeff Walden a écrit :
> If I have one array, and I want to append the contents of an arbitrary
> array to it, and I don't need the unmodified first array after
> appending the second array's elements to it, I have three options.
>
> First, I can use Array.prototype.concat to create a new array
> consisting of the first array, then the contents of the second. But
> this creates a new array rather than mutating the first array, so it
> potentially wastes memory proportional to the size of the first array,
> barring complicated heuristics to recognize and avoid the waste.
> Potentially worse, if any element of the second array is an Array,
> instead of that array being appended, its elements will be appended.
>
> Second, I can use Array.prototype.push:
>
> Array.prototype.push.apply(firstArray, secondArray);
>
> This avoids the memory-wastefulness concern, and it doesn't treat
> Array items specially. But it introduces a third concern: the
> JavaScript stack size limit, if the second array contains a
> particularly large number of elements. This might manifest itself as
> causing a stack overflow exception, or it might cause only some of the
> elements of the second array to be appended (an arguably buggy
> mitigation mechanism, but one some engines use, at least currently).
>
> Third, I can use Array.prototype.splice, passing in |start = length|
> and |deleteCount = 0|. But splice too encounters the stack size limit
> problem. Worse, because its arguments are (start, deleteCount,
> newElt1, newElt2, ...), constructing the array of arguments with which
> to apply the splice method seems to require complicated copy-on-write
> array-element-sharing to mutate the first array without consuming
> twice the first array's memory, or some other tricky scheme. For such
> schemes to be effective here, the programmer would have to structure
> his code pretty carefully, being sure to only use
> Array.prototype.unshift, say, to implement it. And there's a
> bootstrapping problem to creating the array of arguments to supply to
> splice in order to append the elements of an array to the first array.
>
> I see no problem-free way to append an array's elements to another
> array without doing it manually. That's not hard, but it's
> error-prone, and it's much trickier to recognize and correctly
> optimize. I think there should be a way to append elements of an
> arbitrarily sized array to another array, mutating that array
> in-place, without consuming excess memory. I'm not too concerned about
> its precise semantics or about what it's named. For a starting point
> I'll propose Array.prototype.pushAll (or extend, following Python, but
> again, I don't really care about the exact name right now):
>
> Object.defineProperty(Array.prototype, "pushAll",
> {
> enumerable: false, configurable: true, writable: true,
> value: function pushAll(other)
> {
> "use strict";
> var t = ToObject(this);
> var length = ToUint32(t.length);
> var otherLen = other.length;
> for (var i = 0, j = length; i < otherLen; i++, j++)
> t[j] = other[i];
> t.length = j;
> return void 0;
> },
> });
>
> Comments? Suggestions? Requests for changes?
>
> I also had the thought that it might be

Re: Wanted: standard Array function to append an array's elements to another array

2011-08-01 Thread Jeff Walden

On 07/31/2011 03:57 AM, Andrea Giammarchi wrote:

I agree mine is more a workaround while we need a solution but it's not about Array here, 
it's about number of arguments limit per function so once we have pushAll in place, all 
other methods will still suffer the "apply" problem


True.  It seems to me the fundamental problem is exposing n-ary functionality 
solely through a variadic interface, and not through an interface accepting an 
array.  Such interfaces are moderately handy for quick hacking.  Yet since 
they're not much handier than adding [] around the variadic arguments, I don't 
see that they provide much value.  Which still leaves the problem of the 
existing variadic methods, of course...

Jeff
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Wanted: standard Array function to append an array's elements to another array

2011-07-31 Thread Andrea Giammarchi
I agree mine is more a workaround while we need a solution but it's not
about Array here, it's about number of arguments limit per function so once
we have pushAll in place, all other methods will still suffer the "apply"
problem and it's not about apply either, e.g.

var tooMany = Array(0x).join(",$").replace(
/,\$/g,
function (m,i) {return m + i}
).slice(1);

alert(Function(
tooMany,
"return [" + tooMany + "].length"
)());

Too many parameters in function definition (only 32766 allowed)

So ... this is bad


On Sat, Jul 30, 2011 at 12:10 AM, Jeff Walden  wrote:

> On 07/29/2011 05:22 AM, Andrea Giammarchi wrote:
>
>> to avoid apply limits is actually trivial
>>
>
> More or less, yes.
>
> But it requires the developer to anticipate the concern in advance that the
> elements being appended might consume all available stack space.  I don't
> think most developers think at all about the size of the stack, or about its
> being limited, except when they write a recursive algorithm, intentionally
> or inadvertently, and neglect to correctly implement the base case.  I
> certainly forgot about this concern when I wrote the buggy code which
> initially triggered this request, and I think it's reasonably apparent
> there's a problem when even a JS engine implementer makes this mistake.
>
> Past that, your MAX_LENGTH constant would have to be lower than the max
> length across all JS engines cared about.  I find it concerning that
> something as simple as extending an array with the elements of another array
> would require an implementation-dependent workaround, when this operation is
> built-in functionality in other mainstream languages where mutation is
> common:
>
> C++: vector::insert
> http://www.cplusplus.com/**reference/stl/vector/insert/
>
> C#: List.AddRange
> http://msdn.microsoft.com/en-**us/library/z883w3dc.aspx#Y570
>
> Java: List.addAll
> http://download.oracle.com/**javase/1.5.0/docs/api/java/**util/List.html
>
> Perl: push
> http://perlmeme.org/howtos/**perlfunc/push_function.html
>
> Python: list.extend
> http://docs.python.org/**tutorial/datastructures.html
>
> Ruby: array.concat
> http://www.ruby-doc.org/core/**classes/Array.html#M000224
>
> Jeff
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Wanted: standard Array function to append an array's elements to another array

2011-07-29 Thread Jeff Walden

On 07/29/2011 05:22 AM, Andrea Giammarchi wrote:

to avoid apply limits is actually trivial


More or less, yes.

But it requires the developer to anticipate the concern in advance that the 
elements being appended might consume all available stack space.  I don't think 
most developers think at all about the size of the stack, or about its being 
limited, except when they write a recursive algorithm, intentionally or 
inadvertently, and neglect to correctly implement the base case.  I certainly 
forgot about this concern when I wrote the buggy code which initially triggered 
this request, and I think it's reasonably apparent there's a problem when even 
a JS engine implementer makes this mistake.

Past that, your MAX_LENGTH constant would have to be lower than the max length 
across all JS engines cared about.  I find it concerning that something as 
simple as extending an array with the elements of another array would require 
an implementation-dependent workaround, when this operation is built-in 
functionality in other mainstream languages where mutation is common:

C++: vector::insert
http://www.cplusplus.com/reference/stl/vector/insert/

C#: List.AddRange
http://msdn.microsoft.com/en-us/library/z883w3dc.aspx#Y570

Java: List.addAll
http://download.oracle.com/javase/1.5.0/docs/api/java/util/List.html

Perl: push
http://perlmeme.org/howtos/perlfunc/push_function.html

Python: list.extend
http://docs.python.org/tutorial/datastructures.html

Ruby: array.concat
http://www.ruby-doc.org/core/classes/Array.html#M000224

Jeff
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Wanted: standard Array function to append an array's elements to another array

2011-07-29 Thread Andrea Giammarchi
to avoid apply limits is actually trivial:

var fromCharCode = (function ($fromCharCode, MAX_LENGTH) {
return function fromCharCode(code) {
typeof code == "number" && (code = [code]);
for (var
result = [],
i = 0,
length = code.length;
i < length; i += MAX_LENGTH
) {
result.push($fromCharCode.apply(null, code.slice(i, i +
MAX_LENGTH)));
}
return result.join("");
};
}(String.fromCharCode, 2048));

// example
alert(fromCharCode(80)); // P
alert(fromCharCode([80,81,82,83,84])); // PQRST

about the pushAll I wonder if concat does not do already exactly what you
are looking for, as I wrote in the other thread.

Best Regards,
Andrea Giammarchi

On Mon, Jul 25, 2011 at 10:17 PM, Jeff Walden  wrote:

> It's perhaps worth noting that this problem also occurs with
> String.fromCharCode.  I suspect the need for a version of
> |String.fromCharCode.apply(**null, codesArray)| that always works, even
> for super-big |codesArray|, is rather smaller than for the similar
> Array.prototype.push concern.
>
>
> Jeff
> __**_
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/**listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Wanted: standard Array function to append an array's elements to another array

2011-07-28 Thread Jeff Walden

On 07/27/2011 10:12 PM, Mark S. Miller wrote:

We could debate the pros and cons of this sort of chaining convention in 
general. However, in this case I think the more important issue is API 
consistency.


I was thinking this might actually be more consistent, to return this.  
Consider Array.prototype.sort, for example.  (Or maybe the new length would be 
more consistent with Array.prototype.push, on second thought.)

It does seem a reasonable guideline to return something when something can be 
returned, and not to return nothing.  Returning |undefined| was just my not 
having thought of an obviously meaningful and plausible value to return.  But 
I'm fine with any of these return values -- the pushing-the-array-contents 
business is the only truly important part of the method to me.

Jeff
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Wanted: standard Array function to append an array's elements to another array

2011-07-27 Thread Mark S. Miller
On Wed, Jul 27, 2011 at 9:21 AM, David Flanagan wrote:

> Could you return this instead of undefined so that we can chain calls? For
> example:
>
>   a.pushAll(b).pushAll(c).sort()
>

We could debate the pros and cons of this sort of chaining convention in
general. However, in this case I think the more important issue is API
consistency. The JS built ins are not defined in this style. It would make
the API much less regular and predictable to have some use this chaining
convention while others -- especially similar others like push -- don't.

I think this applies whether pushAll were actually added to EcmaScript or if
it were added as part of a library that makes it appear as if it is an
additional built-in.

-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Wanted: standard Array function to append an array's elements to another array

2011-07-27 Thread David Flanagan

On 7/25/11 12:54 PM, Jeff Walden wrote:

  Object.defineProperty(Array.prototype, "pushAll",
  {
enumerable: false, configurable: true, writable: true,
value: function pushAll(other)
{
  "use strict";
  var t = ToObject(this);
  var length = ToUint32(t.length);
  var otherLen = other.length;
  for (var i = 0, j = length; i < otherLen; i++, j++)
t[j] = other[i];
  t.length = j;
  return void 0;
},
  });

Comments?  Suggestions?  Requests for changes? 
Could you return this instead of undefined so that we can chain calls? 
For example:


   a.pushAll(b).pushAll(c).sort()
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Wanted: standard Array function to append an array's elements to another array

2011-07-25 Thread Jeff Walden

It's perhaps worth noting that this problem also occurs with 
String.fromCharCode.  I suspect the need for a version of 
|String.fromCharCode.apply(null, codesArray)| that always works, even for 
super-big |codesArray|, is rather smaller than for the similar 
Array.prototype.push concern.

Jeff
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Wanted: standard Array function to append an array's elements to another array

2011-07-25 Thread Jeff Walden

If I have one array, and I want to append the contents of an arbitrary array to 
it, and I don't need the unmodified first array after appending the second 
array's elements to it, I have three options.

First, I can use Array.prototype.concat to create a new array consisting of the 
first array, then the contents of the second.  But this creates a new array 
rather than mutating the first array, so it potentially wastes memory 
proportional to the size of the first array, barring complicated heuristics to 
recognize and avoid the waste.  Potentially worse, if any element of the second 
array is an Array, instead of that array being appended, its elements will be 
appended.

Second, I can use Array.prototype.push:

  Array.prototype.push.apply(firstArray, secondArray);

This avoids the memory-wastefulness concern, and it doesn't treat Array items 
specially.  But it introduces a third concern: the JavaScript stack size limit, 
if the second array contains a particularly large number of elements.  This 
might manifest itself as causing a stack overflow exception, or it might cause 
only some of the elements of the second array to be appended (an arguably buggy 
mitigation mechanism, but one some engines use, at least currently).

Third, I can use Array.prototype.splice, passing in |start = length| and 
|deleteCount = 0|.  But splice too encounters the stack size limit problem.  
Worse, because its arguments are (start, deleteCount, newElt1, newElt2, ...), 
constructing the array of arguments with which to apply the splice method seems 
to require complicated copy-on-write array-element-sharing to mutate the first 
array without consuming twice the first array's memory, or some other tricky 
scheme.  For such schemes to be effective here, the programmer would have to 
structure his code pretty carefully, being sure to only use 
Array.prototype.unshift, say, to implement it.  And there's a bootstrapping 
problem to creating the array of arguments to supply to splice in order to 
append the elements of an array to the first array.

I see no problem-free way to append an array's elements to another array 
without doing it manually.  That's not hard, but it's error-prone, and it's 
much trickier to recognize and correctly optimize.  I think there should be a 
way to append elements of an arbitrarily sized array to another array, mutating 
that array in-place, without consuming excess memory.  I'm not too concerned 
about its precise semantics or about what it's named.  For a starting point 
I'll propose Array.prototype.pushAll (or extend, following Python, but again, I 
don't really care about the exact name right now):

  Object.defineProperty(Array.prototype, "pushAll",
  {
enumerable: false, configurable: true, writable: true,
value: function pushAll(other)
{
  "use strict";
  var t = ToObject(this);
  var length = ToUint32(t.length);
  var otherLen = other.length;
  for (var i = 0, j = length; i < otherLen; i++, j++)
t[j] = other[i];
  t.length = j;
  return void 0;
},
  });

Comments?  Suggestions?  Requests for changes?

I also had the thought that it might be nice to be able to push a subrange of 
the elements of an array.  You could do that by adding optional |start, length| 
or |start, end| arguments to the method, with corresponding implementation 
changes.  I'm not sure whether this would be useful enough to warrant the 
complexity, but it would be easy to add if people thought it made sense.

Jeff
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss