<story><title>Fixing for loops in Go 1.22</title><url>https://go.dev/blog/loopvar-preview</url></story><parent_chain><item><author>travisd</author><text>It&amp;#x27;s worth noting that it&amp;#x27;s much less of a problem in Python due to the lack of ergonomic closures&amp;#x2F;lambdas. You have to construct rather esoteric looking code for it to be a problem.&lt;p&gt;&lt;pre&gt;&lt;code&gt;    add_n = []
    for n in range(10):
        add_n.append(lambda x: x + n)
    add_n[9](10)  # 19
    add_n[0](10)  # 19
&lt;/code&gt;&lt;/pre&gt;
This isn&amp;#x27;t to say it&amp;#x27;s *not* a footgun (and it has bit me in Python before), but it&amp;#x27;s much worse in Go due to the idiomatic use of goroutines in a loop:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    for i := 0; i &amp;lt; 10; i++ {
        go func() { fmt.Printf(&amp;quot;num: %d\n&amp;quot;, i) }()
    }&lt;/code&gt;&lt;/pre&gt;</text></item><item><author>nerdponx</author><text>Meanwhile Python has received this same feature request many times over the years, and the answer is always that it would break existing code for little major benefit &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;discuss.python.org&amp;#x2F;t&amp;#x2F;make-lambdas-proper-closures&amp;#x2F;10553&quot; rel=&quot;nofollow noreferrer&quot;&gt;https:&amp;#x2F;&amp;#x2F;discuss.python.org&amp;#x2F;t&amp;#x2F;make-lambdas-proper-closures&amp;#x2F;10...&lt;/a&gt;&lt;p&gt;Given how much of an uproar there was over changing the string type in the Python 2 -&amp;gt; 3 transition, I can&amp;#x27;t imagine this change would ever end up in Python before a 4.0.&lt;p&gt;Cue someone arguing about how bad Python is because it won&amp;#x27;t fix these things, and then arguing about how bad Python is because their scripts from 2003 stopped working...</text></item><item><author>AaronFriel</author><text>The C# language team encountered this as well, after introducing lightweight closures in C# 4.0 it quickly became apparent that this was a footgun. Users almost always used loop variables incorrectly, and C# 5.0 made the breaking change.&lt;p&gt;Eric Lippert has a wonderful blog on the &amp;quot;why&amp;quot; from their perspective: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;ericlippert.com&amp;#x2F;2009&amp;#x2F;11&amp;#x2F;12&amp;#x2F;closing-over-the-loop-variable-considered-harmful-part-one&amp;#x2F;&quot; rel=&quot;nofollow noreferrer&quot;&gt;https:&amp;#x2F;&amp;#x2F;ericlippert.com&amp;#x2F;2009&amp;#x2F;11&amp;#x2F;12&amp;#x2F;closing-over-the-loop-var...&lt;/a&gt;&lt;p&gt;I had a bit of trouble finding the original C# 5 announcement; that&amp;#x27;s hopefully not been lost in the (several?) blog migrations on the Microsoft domain since 2012.</text></item></parent_chain><comment><author>eru</author><text>In Python you are much more likely to hit that problem not with closures constructed with an explicit &amp;#x27;lambda&amp;#x27;, but with generator-comprehension expressions.&lt;p&gt;&lt;pre&gt;&lt;code&gt;    (((i, j) for i in &amp;quot;abc&amp;quot;) for j in range(3))
&lt;/code&gt;&lt;/pre&gt;
The values of the above depends on in which order you evaluate the whole thing.&lt;p&gt;(Do take what I wrote with a grain of salt.  Either the above is already a problem, or perhaps you also need to mix in list-comprehension expressions, too, to surface the bug.)</text></comment>
<story><title>Fixing for loops in Go 1.22</title><url>https://go.dev/blog/loopvar-preview</url></story><parent_chain><item><author>travisd</author><text>It&amp;#x27;s worth noting that it&amp;#x27;s much less of a problem in Python due to the lack of ergonomic closures&amp;#x2F;lambdas. You have to construct rather esoteric looking code for it to be a problem.&lt;p&gt;&lt;pre&gt;&lt;code&gt;    add_n = []
    for n in range(10):
        add_n.append(lambda x: x + n)
    add_n[9](10)  # 19
    add_n[0](10)  # 19
&lt;/code&gt;&lt;/pre&gt;
This isn&amp;#x27;t to say it&amp;#x27;s *not* a footgun (and it has bit me in Python before), but it&amp;#x27;s much worse in Go due to the idiomatic use of goroutines in a loop:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    for i := 0; i &amp;lt; 10; i++ {
        go func() { fmt.Printf(&amp;quot;num: %d\n&amp;quot;, i) }()
    }&lt;/code&gt;&lt;/pre&gt;</text></item><item><author>nerdponx</author><text>Meanwhile Python has received this same feature request many times over the years, and the answer is always that it would break existing code for little major benefit &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;discuss.python.org&amp;#x2F;t&amp;#x2F;make-lambdas-proper-closures&amp;#x2F;10553&quot; rel=&quot;nofollow noreferrer&quot;&gt;https:&amp;#x2F;&amp;#x2F;discuss.python.org&amp;#x2F;t&amp;#x2F;make-lambdas-proper-closures&amp;#x2F;10...&lt;/a&gt;&lt;p&gt;Given how much of an uproar there was over changing the string type in the Python 2 -&amp;gt; 3 transition, I can&amp;#x27;t imagine this change would ever end up in Python before a 4.0.&lt;p&gt;Cue someone arguing about how bad Python is because it won&amp;#x27;t fix these things, and then arguing about how bad Python is because their scripts from 2003 stopped working...</text></item><item><author>AaronFriel</author><text>The C# language team encountered this as well, after introducing lightweight closures in C# 4.0 it quickly became apparent that this was a footgun. Users almost always used loop variables incorrectly, and C# 5.0 made the breaking change.&lt;p&gt;Eric Lippert has a wonderful blog on the &amp;quot;why&amp;quot; from their perspective: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;ericlippert.com&amp;#x2F;2009&amp;#x2F;11&amp;#x2F;12&amp;#x2F;closing-over-the-loop-variable-considered-harmful-part-one&amp;#x2F;&quot; rel=&quot;nofollow noreferrer&quot;&gt;https:&amp;#x2F;&amp;#x2F;ericlippert.com&amp;#x2F;2009&amp;#x2F;11&amp;#x2F;12&amp;#x2F;closing-over-the-loop-var...&lt;/a&gt;&lt;p&gt;I had a bit of trouble finding the original C# 5 announcement; that&amp;#x27;s hopefully not been lost in the (several?) blog migrations on the Microsoft domain since 2012.</text></item></parent_chain><comment><author>hinkley</author><text>Everyone else solved this problem by using list comprehensions instead. Rob has surely heard of those.</text></comment>