<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Python&#8217;s lambda is broken!</title>
	<atom:link href="http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/feed/" rel="self" type="application/rss+xml" />
	<link>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/</link>
	<description>Mathematics for computers</description>
	<lastBuildDate>Mon, 30 Jan 2012 07:14:48 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2-beta2-18055</generator>
	<item>
		<title>By: John Powell</title>
		<link>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/comment-page-1/#comment-16502</link>
		<dc:creator>John Powell</dc:creator>
		<pubDate>Mon, 11 Jul 2011 15:28:41 +0000</pubDate>
		<guid isPermaLink="false">http://math.andrej.com/?p=184#comment-16502</guid>
		<description>Following on from what Svat said, in introductory javascript books, there is always a warning about assigning event listeners in loops with the value for the loop exit condition being assigned, instead of the 1, 2, 3, etc expected. The solution given is to use a closure and the &lt;code&gt;(function(n){})(n);&lt;/code&gt; construct.
[sourcecode gutter=&quot;false&quot;][/sourcecode]
var fs = {};
for(var i=0; i&lt;5; i++) {
fs[i]= (function(i){
return function(n) { return n+i; }
})(i);
}

for(var j in fs) {
  console.log(&quot;fs[&quot; + j +&quot;] =&quot; ,fs[j](100));
}

I am reasonably new to functional programming, but the supposed &quot;issue&quot; with python seems quite reasonable when viewed through javascript eyes.</description>
		<content:encoded><![CDATA[<p>Following on from what Svat said, in introductory javascript books, there is always a warning about assigning event listeners in loops with the value for the loop exit condition being assigned, instead of the 1, 2, 3, etc expected. The solution given is to use a closure and the <code>(function(n){})(n);</code> construct.<br />
[/sourcecode]<br />
var fs = {};<br />
for(var i=0; i&lt;5; i++) {<br />
fs[i]= (function(i){<br />
return function(n) { return n+i; }<br />
})(i);<br />
}</p>
<p>for(var j in fs) {<br />
  console.log(&quot;fs[&quot; + j +&quot;] =&quot; ,fs[j](100));<br />
}</p>
<p>I am reasonably new to functional programming, but the supposed &#8220;issue&#8221; with python seems quite reasonable when viewed through javascript eyes.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Matteo</title>
		<link>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/comment-page-1/#comment-16065</link>
		<dc:creator>Matteo</dc:creator>
		<pubDate>Wed, 18 May 2011 19:58:01 +0000</pubDate>
		<guid isPermaLink="false">http://math.andrej.com/?p=184#comment-16065</guid>
		<description>Well this is my first try with Ruby:

fns = (0..9).collect {&#124;i&#124; lambda {&#124;n&#124; i + n}}
  
p fns[3].call(4)

indeed it prints 7 :-)</description>
		<content:encoded><![CDATA[<p>Well this is my first try with Ruby:</p>
<p>fns = (0..9).collect {|i| lambda {|n| i + n}}</p>
<p>p fns[3].call(4)</p>
<p>indeed it prints 7 :-)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Frank Atanassow</title>
		<link>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/comment-page-1/#comment-16013</link>
		<dc:creator>Frank Atanassow</dc:creator>
		<pubDate>Sun, 08 May 2011 17:09:15 +0000</pubDate>
		<guid isPermaLink="false">http://math.andrej.com/?p=184#comment-16013</guid>
		<description>Andrej, was just checking back and noticed someone had already given my explanation about location vs. value. Then I noticed your remark about the comprehension leaving &lt;code&gt;i&lt;/code&gt; in the global scope. (I agree this is laughable.) I wondered if my explanation was wrong and Python was just referencing the leftover global &lt;code&gt;i&lt;/code&gt;. Actually, it seems both explanations are right, since you can alter the value of the closure by assigning to the leftover global!

&lt;code&gt;
&gt;&gt;&gt; i=2
&gt;&gt;&gt; i
2
&gt;&gt;&gt; fs = [(lambda n: i + n) for i in range(10)]
&gt;&gt;&gt; fs[3](0)
9
&gt;&gt;&gt; i
9
&gt;&gt;&gt; i = 0
&gt;&gt;&gt; fs[3](4)
4
&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>Andrej, was just checking back and noticed someone had already given my explanation about location vs. value. Then I noticed your remark about the comprehension leaving <code>i</code> in the global scope. (I agree this is laughable.) I wondered if my explanation was wrong and Python was just referencing the leftover global <code>i</code>. Actually, it seems both explanations are right, since you can alter the value of the closure by assigning to the leftover global!</p>
<p><code><br />
&gt;&gt;&gt; i=2<br />
&gt;&gt;&gt; i<br />
2<br />
&gt;&gt;&gt; fs = [(lambda n: i + n) for i in range(10)]<br />
&gt;&gt;&gt; fs[3](0)<br />
9<br />
&gt;&gt;&gt; i<br />
9<br />
&gt;&gt;&gt; i = 0<br />
&gt;&gt;&gt; fs[3](4)<br />
4<br />
</code></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Frank Atanassow</title>
		<link>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/comment-page-1/#comment-16011</link>
		<dc:creator>Frank Atanassow</dc:creator>
		<pubDate>Sat, 07 May 2011 22:33:44 +0000</pubDate>
		<guid isPermaLink="false">http://math.andrej.com/?p=184#comment-16011</guid>
		<description>I know this discussion is long since over, but I recall talking about the very same issue recently on somebody else&#039;s blog and, as far as I can see, all the explanations here are incorrect. (All the ones there were too; it&#039;s tricky.) The issue is not scoping or broken lambda-expressions; rather, it depends on the fact that Python implements list comprehensions via mutation.

For my reference and yours, here is your first example:

&lt;code&gt;
&gt;&gt;&gt; fs = [(lambda n: i + n) for i in range(10)]
&gt;&gt;&gt; fs[3](4)
13
&lt;/code&gt;

When the lambda-expression is evaluated, the variable &lt;code&gt;i&lt;/code&gt; is properly captured in a closure. In Python, a variable is, as you know, a reference to a mutable cell. However, Python list comprehension is evaluated by updating &lt;code&gt;i&lt;/code&gt; for each element in the domain, not rebinding it. This means that you are creating 10 closures with 10 copies of references to the same mutable cell. By the time &lt;code&gt;fs&lt;/code&gt; is bound, the comprehension has been evaluated, so the value in the cell is 10, so each dereference will return 10.

In contrast, in Ocaml the &lt;code&gt;for-do&lt;/code&gt; construct is implemented by rebinding the index for each evaluation of the body. However, if you were to implement list comprehensions using camlp4 in the same way as Python, by mutation, you might encounter the same problem in Ocaml, depending on whether you you capture the cell or its contents.

This code, which is the natural and erroneous solution:

&lt;code&gt;
[ (fun n -&gt; !i + n) for i in 1 to 10]
&lt;/code&gt;

would behave like the Python code, because the cell is captured and only dereferenced after the list is built.

This code:

&lt;code&gt;
[ let i&#039; = !i in (fun n -&gt; i&#039; + n) for i in 1 to 10 ]
&lt;/code&gt;

would behave as you expected, because &lt;code&gt;i&lt;/code&gt; is dereferenced while the list is being built.

I don&#039;t know if Python provides a way to get the same effect (I am a Haskeller); it displays the usual imperative confusion between variables and cells. But I think I&#039;ve demonstrated that, at least in this respect, Python&#039;s lambda does not behave any differently than you would expect an ML language&#039;s to behave.</description>
		<content:encoded><![CDATA[<p>I know this discussion is long since over, but I recall talking about the very same issue recently on somebody else&#8217;s blog and, as far as I can see, all the explanations here are incorrect. (All the ones there were too; it&#8217;s tricky.) The issue is not scoping or broken lambda-expressions; rather, it depends on the fact that Python implements list comprehensions via mutation.</p>
<p>For my reference and yours, here is your first example:</p>
<p><code><br />
&gt;&gt;&gt; fs = [(lambda n: i + n) for i in range(10)]<br />
&gt;&gt;&gt; fs[3](4)<br />
13<br />
</code></p>
<p>When the lambda-expression is evaluated, the variable <code>i</code> is properly captured in a closure. In Python, a variable is, as you know, a reference to a mutable cell. However, Python list comprehension is evaluated by updating <code>i</code> for each element in the domain, not rebinding it. This means that you are creating 10 closures with 10 copies of references to the same mutable cell. By the time <code>fs</code> is bound, the comprehension has been evaluated, so the value in the cell is 10, so each dereference will return 10.</p>
<p>In contrast, in Ocaml the <code>for-do</code> construct is implemented by rebinding the index for each evaluation of the body. However, if you were to implement list comprehensions using camlp4 in the same way as Python, by mutation, you might encounter the same problem in Ocaml, depending on whether you you capture the cell or its contents.</p>
<p>This code, which is the natural and erroneous solution:</p>
<p><code><br />
[ (fun n -&gt; !i + n) for i in 1 to 10]<br />
</code></p>
<p>would behave like the Python code, because the cell is captured and only dereferenced after the list is built.</p>
<p>This code:</p>
<p><code><br />
[ let i' = !i in (fun n -&gt; i' + n) for i in 1 to 10 ]<br />
</code></p>
<p>would behave as you expected, because <code>i</code> is dereferenced while the list is being built.</p>
<p>I don&#8217;t know if Python provides a way to get the same effect (I am a Haskeller); it displays the usual imperative confusion between variables and cells. But I think I&#8217;ve demonstrated that, at least in this respect, Python&#8217;s lambda does not behave any differently than you would expect an ML language&#8217;s to behave.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Lambda expressions in Python « dsimkhada</title>
		<link>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/comment-page-1/#comment-15730</link>
		<dc:creator>Lambda expressions in Python « dsimkhada</dc:creator>
		<pubDate>Fri, 08 Apr 2011 18:38:52 +0000</pubDate>
		<guid isPermaLink="false">http://math.andrej.com/?p=184#comment-15730</guid>
		<description>[...] http://docs.python.org/reference/expressions.html#lambda [2] http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/ [3] http://diveintopython.org/power_of_introspection/lambda_functions.html [4] [...]</description>
		<content:encoded><![CDATA[<p>[...] <a href="http://docs.python.org/reference/expressions.html#lambda" rel="nofollow">http://docs.python.org/reference/expressions.html#lambda</a> [2] <a href="http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/" rel="nofollow">http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/</a> [3] <a href="http://diveintopython.org/power_of_introspection/lambda_functions.html" rel="nofollow">http://diveintopython.org/power_of_introspection/lambda_functions.html</a> [4] [...]</p>
]]></content:encoded>
	</item>
</channel>
</rss>

