Chris's Wiki :: blog/python/AClosureConfusion Commentshttps://utcc.utoronto.ca/~cks/space/blog/python/AClosureConfusion?atomcommentsDWiki2005-12-30T05:16:23ZRecent comments in Chris's Wiki :: blog/python/AClosureConfusion.By Chris Siebenmann on /blog/python/AClosureConfusiontag:CSpace:blog/python/AClosureConfusion:774b39320cb1dee20e9e0b2ff27b82c07d4f332dChris Siebenmann<div class="wikitext"><p>I suspect that <code>range()</code> has the semantics it does so that
'<code>range(0, len(lst))</code>' works right to create a list of indexes
that exactly covers all elements of the list. In fact, the start
value is optional and defaults to 0, so you can just write
'<code>range(len(lst))</code>'.
</p>
<p>A fair amount of things in Python seem to be carefully designed to
combine well with lists and sequences. (I wrote about another one of
these in <a href="https://utcc.utoronto.ca/~cks/space/blog/python/SmallDetailsMatter">SmallDetailsMatter</a>.)</p>
</div>2005-12-30T05:16:23ZFrom 70.231.184.201 on /blog/python/AClosureConfusiontag:CSpace:blog/python/AClosureConfusion:8cf9282b6c4c50fff2888932acfd18702ba13c9bFrom 70.231.184.201<div class="wikitext"><p>I'd assumed that, it still just seems strange.
</p>
<p>For example, mathematics has a notation for 'open' and 'closed' intervals: (0,10) on the integers is the same as [1,9] on the integers, so you could view this as saying that 'range(i,j)' specifies [i,j). And that just seems weird to me, because I can't think of any context in which that's natural. The mathematical notation for that, [i,j), is asymmetric. It matches the traditional C loop style 'for(x=i; x<j; ++x)', so I can see why it might be <em>convenient</em> when expressing things, e.g. adjacent non-overlapping intervals, but it seems to me one of the worst possible choices for plausibility and intelligibility. In the C for() loop the two are not referenced symmetrically, so it's not as surprising.
</p>
<p>(Of course, you didn't help matters by using 'range(1,10)' where the traditional thing along those lines would be 'range(1,11)', but I dunno, maybe this is a really common example range in python to help beat into people's skull what it means.)
</p>
<p>--nothings</p>
</div>2005-12-30T04:58:03ZBy Chris Siebenmann on /blog/python/AClosureConfusiontag:CSpace:blog/python/AClosureConfusion:66b3254bb69487f91bd6b29d8019777707d1f8eaChris Siebenmann<div class="wikitext"><p>I need to write a longer proper reply, but to cover the quick stuff:
</p>
<p><code>range(i,j)</code> generates a list from i to j-1, so <code>range(1,10)</code> generates
a list of 1 to 9. Then the <code>for</code> loop iterates through this list, leaving
<code>i</code> set to the list's last element when it terminates. The combination
leaves <code>i</code> set to 9 after the loop is over.
</p>
<p>(Thus Python <code>for</code> is more like awk's <code>foreach</code> than C's <code>for</code>.
C style <code>for</code> loops are generally written with <code>while</code> in Python.)</p>
</div>2005-12-29T20:39:25ZFrom 70.231.184.201 on /blog/python/AClosureConfusiontag:CSpace:blog/python/AClosureConfusion:06444048acf38d81454359a866a6c58c974199b8From 70.231.184.201<div class="wikitext"><p>I don't know python, so this example is particuarly confusing: why isn't the output '10 10' (or even '11 11', but I guess that's a separate oddity)? Indeed, why isn't the output 'exception, variable unbound'?
</p>
<p>That is, in a C-like language I'm used to the idea that you can look in the 'i' slot after using it in a for loop and see it having the succeeding value; it seems weird to have a higher-level-language than C that allows the variable to have a meaningful value afterwards, and indeed this sort of bug seems like exactly the reason you wouldn't want it to (it's almost certainly never what you want, at least if used in a closure). Perhaps one should flag it (as much as possible, which probably isn't very much) at compile time: "loop index variable escapes the loop through closures".
</p>
<p>"Stack frames" is of course exactly the wrong term, since with closures your variables can't be bound to stack frames anyway, since they can escape!
</p>
<p>The javascript link you post to seems to actually indicate that the problem is really that <code>var x = array[i];</code> doesn't actually create a new variable x with whatever values is in array[i] at that instant, but rather a reference to array[i] indirected through both of <em>those</em> slots!
</p>
<p>I say this because what's described in that article is exactly what I would recommend to explain the "scope" answer and to solve the problem, rather than going through another function. Using some hypothetical language:
</p>
<pre>
for i in 1..10 do {
ll.append(func(x){i+x;});
}
</pre>
<p>should reasonably report "10 10" or possibly "11 11", and
</p>
<pre>
for i in 1..10 do {
var j = i;
ll.append(func(x){j+x;});
}
</pre>
<p>should reasonably report "1 10".
</p>
<p>A language for which the j-declaration-and-assignment inside the loop doesn't have the effect of ML/Lisp's <code>let</code>, of creating a brand new slot every time through the loop, yet supports closures, is just broken. It's the only sane semantic.
</p>
<p>Note that this whole mess is clearer if, if you're going to allow index variables to escape their loops, you either:
</p>
<ul><li>Make each iteration generate a new copy of the variable, a la my comment above about LET, in which case the "you are a dumb idiot with your naive solution" works correctly (and this is actually a perfectly reasonable semantic from a high-level language semantics POV; the traditional semantic follows from implementation issues of "how do you iterate, producing the values 1 to 10 sequentially").
</li>
<li>Require index variables to be declared outside the loop so the duration of the slot-sharing follows unambiguously from the lexical scoping. E.g., C++-style loop declarations are misleading for loops in languages with closures.
</li>
</ul>
<p>I imagine the first of those points has been addressed in the literature, but I don't know where to look.
</p>
<p>--nothings</p>
</div>2005-12-29T09:44:17Z