lua-users home
lua-l archive

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


Consider the following:

    local function _unwind_helper( fn, args, n, success, ... )
        if not success then
            pcall( fn, unpack( args, 1, n ) )
            local msg = ...
            error( msg, 0 )
        else
            fn( unpack( args, 1, n ) )
            return ...
        end
    end

    function unwind_protect( fn, ... )
        local n = select( '#', ... )
        local args = { ... }
        return function( ... )
            return _unwind_helper( fn, args, n, pcall( ... ) )
        end
    end

Usage:

    local f = io.open( "foo.txt" )

    unwind_protect( io.close, f )( function()
        print( f:read( "*a" ) )
    end )

With syntactic sugar for closure arguments, we get:

    unwind_protect( io.close, f ) do
        print( f:read( "*a" ) )
    end

Admittedly, this is only slightly lighter weight, but it does help.

On the other hand, it behaves unexpectedly if we write:

    local f = io.open( "foo.txt" )

    unwind_protect( io.close, f ) do
        return f:read( "*a" )
    end

I think one would end up needing to look at how Modula-3 defined function
returns in terms of exceptions but that still makes the behavior of pcall
"interesting" since one would then need to be prepared for it intercepting a
non-local function return.

Using the above assumed sugar, we could also have written the odder looking:

    local f = io.open( "foo.txt" )

    unwind_protect do io.close( f ) end dp
        print( f:read( "*a" ) )
    end

I'm not sure that that helps things much...

Mark