[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: Another example for syntactically lightweight closures
- From: David Manura <dm.lua@...>
- Date: Tue, 5 Feb 2008 04:24:30 +0000 (UTC)
Mark Hamburg writes:
> Consider the following: ...
> local f = io.open( "foo.txt" )
> unwind_protect( io.close, f )( function()
> print( f:read( "*a" ) )
> end )
If you'll need to unwind multiple objects, an approach similar to  could be
local f = io.open('in.txt' ); stk:finally(io.close, f)
local f2 = io.open('out.txt', 'w'); stk:finally(io.close, f2)
Structurally, that is similar to the proposal in  but with the semantics of
local f = io.open('in.txt' ); finally io.close(f) end
local f2 = io.open('out.txt', 'w'); finally io.close(f2) end
> On the other hand, it behaves unexpectedly if we write:...
> unwind_protect( io.close, f ) do
> return f:read( "*a" )
True, unless Lua is somehow extended so that a function like "unwind_protect"
could itself trigger a return in its caller (like certain control structures can
do). We maybe could extend the CALL opcode to conditionally cause a RETURN if
the called function sets some flag.
The major question I have is whether "do" should be syntactic sugar for
"function()". This "do" syntax has been proposed before and even implemented as
If so, then it would seem consistent to allow something like this:
function f() do return g() end end
to be rewritten equivalently as this:
function f() function() return g() end end
Does that make sense? "function() return g() end" is normally an expression,
but it's being used here as a statement, and in that context it is getting
evaluated. (Lua does allow that a function call "g()" be interpreted as either
an expression or a statement though.)
Similarly, then, should these have identical behavior?
while a do b() end
while a function b() end
Should we even allow this?
local h = function() return g() end
function f() h end
Maybe that goes too far...h evaluates to a function only at run-time. For
similar reasons we want that
function g() do return 2 end; return 3 end -- returns 2
function g() function() return 2 end; return 3 end -- returns 2
function f() return 2 end
function g() f(); return 3 end -- returns 3
Another consideration is that the following two statements are currently
considered equivalent according to the language specification:
local f = function() return end
local f = function() end
so then should these two also be equivalent?
while true do return end
while true do end
Obviously, not. To reconcile this, "function() return end" and "function() end"
must be considered as different.
In practice, the two do actually generate different byte codes:
1  RETURN 0 1
2  RETURN 0 1
1  RETURN 0 1
That currently isn't defined behavior, but maybe it is a convenient one that
could be used as the above mentioned differentiating "flag" permitting
function f() try(do return 2 end) return 3 end
assert(f() == 2) -- Yes, the "try" function can somehow forward
-- the "return 2" under the "CALL opcode"
-- extension noted above.
So, do we really want "do" to be syntactic sugar for "function()"?
Incidentally, I'm working on a patch that would extend "do ... end" not
necessarily as syntax sugar for closures but rather to allow something like this
local a = do local b = c*c; if b < 2 then return end end
which would behave like
local a; do
local b = c*c
if b < 2 then return end
a = b+1
That is, the expression "do <chunk> end <expr>" evaluates to the expression
"<expr>" inside the lexical scope of "<chunk>". I believe Rici and I had
similar ideas that differed only in surface syntax (e.g. "let <chunk> in
<expr>" rather than "do <chunk> end <expr>").
 http://lua-users.org/wiki/LuaPowerPatches - "Do patch", Asko Kauppi