[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: "dynamic" closures
- From: Mark Hamburg <mark@...>
- Date: Mon, 30 Nov 2009 18:53:43 -0800
On Nov 30, 2009, at 3:12 AM, spir wrote:
> Was trying to understand Lua closures better (the indications in historical docs are not enough for my limited brain), when I stepped on this:
> x = 1
> function f()
> n = 1
> function g(a)
> print (x + n + a)
> return g
> g= f()
> g(1) --> 3
> x = 2
> g(1) --> 4
> I'm a bit surprised the code works "as unexpected" ;-) As a consequence, g becomes totally referentially "opaque", or do I misinterpret? (Maybe I miss a basic point, but for me this smells strong like naughty bugs. Even more since x is a global.) Do you have use cases for such an idiom (that could hardly be refactored into harmless expression)?
> About implementation, it seems to indicate Lua embebs symbolic references (*) to outer _variables_ in reachable scopes, when creating a closure for g0. Not pointer references (**) to _values_; otherwise the replacement of x would not be seen by the closure. Before trying, I thought the outcome would be 3, meaning values are kind of frozen at closure creation time (would be the case if references were pointers).
> [I imagine this behaviour may match the one of closures in functional languages (?), but anyway the whole paradigm is so different...]
This is exactly how true closures work in all languages with closures. The creation of g closes over the references to n and x (which as you've written them are global but might as well be local -- you'll get the same results). If you use local variables, a new instance of n is created whenever x is executed, but there is presumably only one point where x is created hence all references lead back to the same value.
Perhaps you have experience with a poor man's closure implementation in which the values are copied into the closure at the time the closure is created? That meets many of the needs of a closure, but it is just a weak copy. Consider for example wanting to write:
local sum = 0
table.foreachi( array, function( i, v ) sum = sum + v end )
print( "Sum = ", sum )
In order for this to work, the reference to sum in the function have to refer to the mutable variable declared outside the function.