lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

On Nov 30, 2009, at 3:12 AM, spir wrote:

> Hello,
> 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) 
>  end
>  return g
> end
> 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...]
> Denis

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.