mozilla

Revision 124963 of 1.7

  • Revision slug: Talk:JavaScript/New_in_JavaScript/1.7
  • Revision title: 1.7
  • Revision id: 124963
  • Created:
  • Creator: Nickolay
  • Is current revision? No
  • Comment /* Syntax for replacing native iterators? */

Revision Content

Spent Iterators Should Not Throw an Exception

Exceptions should be used when there is a runtime error, not when a normal termination condition occurs. When calling it.next() on an iterator, the return value of that call should indicate the status of the iterator. The value returned should probably be null, but I'd be willing to entertain arguments for false, undefined, or something of the sort.

Throwing an exception to handle a normal case like a spent iterator will cause developers to litter code with try/catch blocks and create an enormous amount of unnecessary complexity. Code like the following should be possible in the spirit of JS and other languages that support similar constructs:

while ((item = it.next()) !== null)
{
    print(item);
}

h3h 16:56, 1 June 2006 (PDT)

The problem with returning a special value is that whatever value you choose can't be produced by the iterator.

The design of this feature is very similar to Python's, and the same discussion happened between the Python developers in 2001. They reached the conclusion that an exception is the best way to handle termination of an iterator. See python-dev threads such as "why not "return StopIteration"?", which quotes from the Python Enhancement Proposal that introduced iterators, PEP 234.

Experience with this design in Python has shown that developers don't often have to explicitly call the next method or catch the exception; iterators are usually iterated over in for loops, or passed to functions. Your example would usually be written in JS as

for (var item in it) {
    print(item);
}

or even

printAll(it);

Deltab 08:48, 30 June 2006 (PDT)

I was looking at the yield statement, and it reminded me of the lack of a sleep/suspend/wait function, which makes a lot of code much more painful than it needs to be. Are there any plans to add this kind of function to 1.7?

It would be especially nice if there were a WaitFor(evt) function and a corresponding NotifyThat(evtHappened) so that threads could simply wait until another thread (or the human user!) was finished.

(Apologies if this is the wrong place to raise this.)

--Voracity 00:45, 25 July 2006 (PDT)

Bug in "Row capture and record updating" example?

The final example, it's not clear how newPersonRecord could include the property "name", as "name" was never a property of z (from the previous example).

Should the example use personRecord instead of z?

Tag 22:07, 26 July 2006 (PDT)

Syntax for replacing native iterators?

If you wish to provide a custom iterator, you should override the getter for __iterator__ to return an instance of your custom iterator.

I'm having trouble finding the precise syntax to override these native iterators.

Let's say I want to rewrite the DOM HTMLCollection iterator to return only nodes and ignore the builtin properties (length, item, and namedItem). My code looks something like this:

    var DOMIterator = function(nodeList) {
      var len  = nodeList.length, i = 0, ret;
      for (i = 0; i < len; i++) {
        yield [i, nodeList[i]];
      }
      throw StopIteration;
    };
    
    var nodes = document.getElementsByTagName('p');
    
    nodes.__defineGetter__("__iterator__", function() {
      return new DOMIterator(this);
    });
    

When I evaluate nodes.__iterator__, I get {{mediawiki.external('object Generator')}}. But when I try for (var x in nodes) { /* do something */ }, I get a TypeError ("nodes has invalid __iterator__ value ({})").

I'm sure I've overlooked something simple, but I've tried a crapload of variations on this theme — making the iterator return a function, removing the yield statement and defining an ordinary next method, etc. What am I doing wrong? Savetheclocktower 11:46, 29 July 2006 (PDT)

See --Nickolay 16:45, 29 July 2006 (PDT)

Revision Source

<h3 name="Spent_Iterators_Should_Not_Throw_an_Exception"> Spent Iterators Should Not Throw an Exception </h3>
<p>Exceptions should be used when there is a runtime <b>error</b>, not when a normal termination condition occurs. When calling <code>it.next()</code> on an iterator, the <i>return value</i> of that call should indicate the status of the iterator. The value returned should probably be <code>null</code>, but I'd be willing to entertain arguments for <code>false</code>, <code>undefined</code>, or something of the sort.
</p><p>Throwing an exception to handle a normal case like a spent iterator will cause developers to litter code with <code>try</code>/<code>catch</code> blocks and create an enormous amount of unnecessary complexity. Code like the following should be possible in the spirit of JS and other languages that support similar constructs:
</p>
<pre>while ((item = it.next()) !== null)
{
    print(item);
}</pre>
<p>— <a href="User:H3h">h3h</a> 16:56, 1 June 2006 (PDT)
</p><p>The problem with returning a special value is that whatever value you choose can't be produced by the iterator.
</p><p>The design of this feature is very similar to Python's, and the same discussion happened between the Python developers in 2001. They reached the conclusion that an exception is the best way to handle termination of an iterator. See python-dev threads such as "<a class="external" href="http://mail.python.org/pipermail/python-dev/2001-June/015508.html">why not "return StopIteration"?</a>", which quotes from the Python Enhancement Proposal that introduced iterators, <a class="external" href="http://www.python.org/dev/peps/pep-0234/">PEP 234</a>.
</p><p>Experience with this design in Python has shown that developers don't often have to explicitly call the <code>next</code> method or catch the exception; iterators are usually iterated over in <code>for</code> loops, or passed to functions. Your example would usually be written in JS as
</p>
<pre>for (var item in it) {
    print(item);
}</pre>
<p>or even
</p>
<pre>printAll(it);</pre>
<p>— <a href="User:Deltab">Deltab</a> 08:48, 30 June 2006 (PDT)
</p><p>I was looking at the yield statement, and it reminded me of the lack of a <code>sleep/suspend/wait</code> function, which makes a lot of code much more painful than it needs to be. Are there any plans to add this kind of function to 1.7?
</p><p>It would be especially nice if there were a <code>WaitFor(evt)</code> function and a corresponding <code>NotifyThat(evtHappened)</code> so that threads could simply wait until another thread (or the human user!) was finished.
</p><p>(Apologies if this is the wrong place to raise this.)
</p><p>--<a href="User:Voracity">Voracity</a> 00:45, 25 July 2006 (PDT)
</p>
<h3 name="Bug_in_.22Row_capture_and_record_updating.22_example.3F"> Bug in "Row capture and record updating" example? </h3>
<p>The final example, it's not clear how <code>newPersonRecord</code> could include the property "name", as "name" was never a property of <code>z</code> (from the previous example).
</p><p>Should the example use <code>personRecord</code> instead of <code>z</code>?
</p><p><a href="User:Tag">Tag</a> 22:07, 26 July 2006 (PDT)
</p>
<h3 name="Syntax_for_replacing_native_iterators.3F"> Syntax for replacing native iterators? </h3>
<blockquote>If you wish to provide a custom iterator, you should override the getter for __iterator__ to return an instance of your custom iterator.</blockquote>
<p>I'm having trouble finding the precise syntax to override these native iterators.  
</p><p>Let's say I want to rewrite the DOM <code>HTMLCollection</code> iterator to return only nodes and ignore the builtin properties (length, item, and namedItem).  My code looks something like this:
</p>
<pre>    var DOMIterator = function(nodeList) {
      var len  = nodeList.length, i = 0, ret;
      for (i = 0; i &lt; len; i++) {
        yield [i, nodeList[i]];
      }
      throw StopIteration;
    };
    
    var nodes = document.getElementsByTagName('p');
    
    nodes.__defineGetter__("__iterator__", function() {
      return new DOMIterator(this);
    });
    
</pre>
<p>When I evaluate <code>nodes.__iterator__</code>, I get <code>{{mediawiki.external('object Generator')}}</code>.  But when I try <code>for (var x in nodes) { /* do something */ }</code>, I get a <code>TypeError</code> ("<code>nodes has invalid __iterator__ value ({})</code>").
</p><p>I'm sure I've overlooked something simple, but I've tried a crapload of variations on this theme — making the iterator return a function, removing the <code>yield</code> statement and defining an ordinary <code>next</code> method, etc.  What am I doing wrong? <a href="User:Savetheclocktower">Savetheclocktower</a> 11:46, 29 July 2006 (PDT)
</p>
<dl><dd> See <a class="external" href="http://groups.google.com/group/mozilla.dev.tech.js-engine/browse_thread/thread/d7571ff410e67528/24e39cbd75344230#24e39cbd75344230"> --</a><a href="User:Nickolay">Nickolay</a> 16:45, 29 July 2006 (PDT)
</dd></dl>
Revert to this revision