Side-effects of some Array methods ...
On Jun 27, 2008, at 6:51 AM, Pratap Lakshman (VJ#SDK) wrote:
The side effect is as follows: if “this” does not have a “length”
property, it ends up getting one; if “this” does have a length
property, but is not an Array, that “length” property will get
updated.
True, and not just for pop -- for all generic Array methods that
mutate length.
What is the rationale for this?
I don't recall a detailed rationale on this point, but the pseudo-
code is simplest without a special case that avoids creating a
'length' property if one does not exist, and it's easy to rationalize
"caveat hacker" -- if you wrote Array.prototype.pop.call(p), you
wanted to have effects on your pizza ;-). The simpler specs are a
good thing.
Trying to change this now seems dicey. We don't know if any web
scripts count on this edge case. Creating length may be a requirement
because lazy pizza coders left 'length' out, knowing it would be
created, and then depended on it becoming 0 (e.g., in a < expression
-- if undefined it would become NaN and the condition would be false).
There does not seem to be any profit in taking risk by changing the
semantics.
Back to list ->
On Fri, Jun 27, 2008 at 1:27 PM, Brendan Eich <brendan at mozilla.org> wrote:
On Jun 27, 2008, at 6:51 AM, Pratap Lakshman (VJ#SDK) wrote:
The side effect is as follows: if "this" does not have a "length" property, it ends up getting one; if "this" does have a length property, but is not an Array, that "length" property will get updated.
True, and not just for pop -- for all generic Array methods that mutate length.
What is the rationale for this?
I don't recall a detailed rationale on this point, but the pseudo- code is simplest without a special case that avoids creating a 'length' property if one does not exist, and it's easy to rationalize "caveat hacker" -- if you wrote Array.prototype.pop.call(p), you wanted to have effects on your pizza ;-). The simpler specs are a good thing.
Trying to change this now seems dicey. We don't know if any web scripts count on this edge case. Creating length may be a requirement because lazy pizza coders left 'length' out, knowing it would be created, and then depended on it becoming 0 (e.g., in a < expression -- if undefined it would become NaN and the condition would be false).
There does not seem to be any profit in taking risk by changing the semantics.
A program that called pop() on an object w/no length would know right away if it failed.
Silent failure would also occur with a length property that has the attribute ReadOnly. For example, a String (or Function) object, or a Host object, such as a NodeList (reasonable use case).
javascript:var p = new String("two"); void(Array.prototype.pop.call(p)); alert(p.length);
javascript:var p = document.childNodes; alert(p.length); try{void(Array.prototype.pop.call(p)); alert(p.length);} catch(ex) {alert(ex.name); }
FF: alert 2, then "TypeError" IE: alert 2, then, Choke on ex.name. SF: alert 2 twice, No error Op: alert 1, then "Error"
Should the req be that - length - property be defined on the object itself (not prototype)? If not, [[Put]] will create it if it doesn't already exist. Should the - length - property be checked for either of:
- the absence of ReadOnly attribute, or
- being a property that has a setter
If no check is made, or if a check is made - either way, an error will occur. The difference is where.
<speculation>
ISTM that if IE is going to support generics on Host objects, and going along with that hypothetical scenario and further pretending that Array generics would actually work with Host objects and not be buggy, then, in that case, the Array generics would probably see more widespread use. </speculation>
Now, in the hypothetical scenario, would some built-in algorithmic safety checks help fail faster? Checks for 1) hasOwnProperty and not readonly or 2) has a setter
Garrett
On Jun 27, 2008, at 2:07 PM, Garrett Smith wrote:
A program that called pop() on an object w/no length would know right away if it failed.
Why do you say that?
js> function pizza(){}
js> pizza.prototype.pop = Array.prototype.pop
function pop() { [native code] } js> p =new pizza [object Object] js> p.length
js> p.pop()
js> p.length
0 js> a = []
js> a.pop()
js>
Now, in the hypothetical scenario, would some built-in algorithmic safety checks help fail faster? Checks for 1) hasOwnProperty and not readonly or 2) has a setter
Again, we don't know what failing faster (you mean throwing a new
error as an exception) would break. The shell session above shows how
fail-soft could leave scripts executing and even behaving well.
Throwing an exception that's not caught would rain on such scripts'
parades.
to list ->
On Fri, Jun 27, 2008 at 3:04 PM, Brendan Eich <brendan at mozilla.org> wrote:
On Jun 27, 2008, at 2:07 PM, Garrett Smith wrote:
A program that called pop() on an object w/no length would know right away if it failed.
Why do you say that?
I worded that very poorly. It was in response to:-
"There does not seem to be any profit in taking risk by changing the semantics."
- I should have written: The algorithm could be changed such that program that called pop() on an object w/no length would know right away.
js> function pizza(){} js> pizza.prototype.pop = Array.prototype.pop function pop() { [native code] } js> p =new pizza [object Object] js> p.length js> p.pop() js> p.length 0 js> a = []
js> a.pop() js>
Now, in the hypothetical scenario, would some built-in algorithmic safety checks help fail faster? Checks for 1) hasOwnProperty and not readonly or 2) has a setter
Again, we don't know what failing faster (you mean throwing a new error as an exception) would break. The shell session above shows how fail-soft could leave scripts executing and even behaving well. Throwing an exception that's not caught would rain on such scripts' parades.
I hardly call that a parade. It looks like a toy program aimed at doing nothing useful. If your argument is addressing an object which does not have an own property - length -, then what about calling - pop - on an object that a) has a getter and no setter for - length b) has a - length - property with the attribute ReadOnly (the NodeList example).
How do you address these concern? Is it better to fail fast or fail later? If later, and in the case or attempting to set a ReadOnly property, then should the failure be silent? (String example). What about the NodeList example?
BTW, I am keeping this on ES4 list. IMO, having fewer lists keeps things simpler (fewer language versions would also seem to be simpler).
Garrett
On Jun 27, 2008, at 3:45 PM, Garrett Smith wrote:
to list ->
I am not the one replying to sender only -- all of my replies to you
have cc'ed the list. You have replied twice to me only, then resent
as reply-alls. What mailer are you using?
Again, we don't know what failing faster (you mean throwing a new
error as an exception) would break. The shell session above shows how fail- soft could leave scripts executing and even behaving well. Throwing an
exception that's not caught would rain on such scripts' parades.I hardly call that a parade. It looks like a toy program aimed at
My shell example is not the "parades" plural referenced above, merely
a demo of fail-soft behavior. The unknown web scripts that might
depend on that behavior could be doing useful work based on the
current semantics ("having parades").
How do you address these concern? Is it better to fail fast or fail later? If later, and in the case or attempting to set a ReadOnly property, then should the failure be silent? (String example). What about the NodeList example?
This is not a green-field design exercise. My point is that browsers
do what ES1-3 said (depending on the Array method; generics were
there all along, but some were added IIRC after ES1). Code tends to
depend on detailed semantics (not always, but more often than you'd
think). Why rock the boat?
On Fri, Jun 27, 2008 at 3:57 PM, Brendan Eich <brendan at mozilla.org> wrote:
On Jun 27, 2008, at 3:45 PM, Garrett Smith wrote:
to list ->
I am not the one replying to sender only -- all of my replies to you have cc'ed the list.
I know. I had a mistake and hit 'Reply'. Then, realizing that, I put the message back on the list.
You have replied twice to me only, then resent as reply-alls. What mailer are you using?
Sorry, it was an accident. I meant to put it on the list and hit 'Reply'. I would not mind if you mail me personally. I just had a mistake.
I'm using GMail. I need a web based mailer because I use multiple machines and usually mobile. I'm open to suggestions for a better mailer or alternative to gmail.
[snip]
My shell example is not the "parades" plural referenced above, merely a demo of fail-soft behavior. The unknown web scripts that might depend on that behavior could be doing useful work based on the current semantics ("having parades").
Your point seemed clear (at least to me). I know the idiom "rain on their parade". It is possible that someone expects that behavior , and in fact, that behavior is guaranteed by the current spec.
How do you address these concern? Is it better to fail fast or fail later? If later, and in the case or attempting to set a ReadOnly property, then should the failure be silent? (String example). What about the NodeList example?
This is not a green-field design exercise. My point is that browsers do what ES1-3 said (depending on the Array method; generics were there all along, but some were added IIRC after ES1). Code tends to depend on detailed semantics (not always, but more often than you'd think). Why rock the boat?
I'm just trying to figure out what the best way to handle error condition. It's somewhat related to what Pratap brought up:
| The side effect is as follows: | if "this" does not have a "length" property, it ends up getting one; | if "this" does have a length property, but is not an Array, that | "length" property will get updated. | What is the rationale for this?
Leads to thinking about API design.
I guess it's not bad the way it is. Anyone calling pop() on a NodeList can get what should be expected. OTOH, maybe it's worth considering if a better alternative exists.
What is a green-field design exercise?
Garrett
On Jun 27, 2008, at 10:18 PM, Garrett Smith wrote:
What is a green-field design exercise?
Sorry for the confusing phrase -- I should have written it's not a
clean-slate design opportunity.
I was wondering about the side effects of calling some of the array methods. Specifically, consider steps 4, 9, from the 'pop' method:
15.4.4.6 Array.prototype.pop ( ) The last element of the array is removed from the array and returned.
NOTE The pop function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the pop function can be applied successfully to a host object is implementation-dependent.
The side effect is as follows: if "this" does not have a "length" property, it ends up getting one; if "this" does have a length property, but is not an Array, that "length" property will get updated. What is the rationale for this?
Example: <script>
function pizza() {} var p = new pizza();
document.write("p.length: " + p.length + "<br>");
Array.prototype.pop.call(p); document.write("p.length: " + p.length + "<br>");
function bridge(len) { this.length = len; } var b = new bridge(2);
document.write("b.length: " + b.length + "<br>");
Array.prototype.pop.call(b); document.write("b.length: " + b.length + "<br>"); </script>
pratap