* * * * *
99 ways to program a hex, Part 19: Lua, recursion, closure as callback
Now, instead of passing along data just to be passed to the callback function
[1], we can include such data as part of a closure [2] to the function we
pass to the do_dump() function.
> #!/usr/bin/env lua
> -- ***************************************************************
> --
> -- Copyright 2010 by Sean Conner. All Rights Reserved.
> --
> -- This program is free software: you can redistribute it and/or modify
> -- it under the terms of the GNU General Public License as published by
> -- the Free Software Foundation, either version 3 of the License, or
> -- (at your option) any later version.
> --
> -- This program is distributed in the hope that it will be useful,
> -- but WITHOUT ANY WARRANTY; without even the implied warranty of
> -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> -- GNU General Public License for more details.
> --
> -- You should have received a copy of the GNU General Public License
> -- along with this program. If not, see <
http://www.gnu.org/licenses/>.
> --
> -- Comments, questions and criticisms can be sent to:
[email protected]
> --
> -- ********************************************************************
>
> -- Style: Lua 5.1, recursion, closure as callback
>
> function do_dump(fpout,offset,callback)
> local line = callback(offset)
> if line == nil then return end
> fpout:write(
> string.format("%08X: ",offset),
> line:gsub(".",function(c) return string.format("%02X ",c:byte()) end),
> string.rep(" ",3 * (16 - line:len())),
> line:gsub("%c","."),
> "\n"
> )
> return do_dump(fpout,offset + 16,callback)
> end
>
> -- **********************************************************************
>
> if #arg == 0 then
> print("-----stdin-----")
> do_dump(io.stdout,0,cb,io.stdin)
> else
> for i = 1 , #arg do
> local f = io.open(arg[1],"r")
> io.stdout:write("-----",arg[1],"-----","\n")
> do_dump(io.stdout,0,function(offset) return f:read(16) end)
> f:close()
> end
> end
>
> os.exit(0)
>
Here, our function (which is not named, as you don't really need to name
functions in Lua [3]) references our open file f, but in order to do so, Lua
needs to include a reference to f to the function when said function is
passed to do_dump(). It does so by creating what's called a “closure”—think
of a closure as both a pointer (or reference) to a function, plus a pointer
(or reference) to data that is outside the normal lexical scope [4] of the
function.
And why do I pass in the offset when my unnamed (“anonymous”) function
doesn't use it? Because it might be useful in some contexts to know where to
pull the data (say from a block of memory).
* Part 18: Lua, recursion, callback [5]
* Part 20: C89, const correctness, assertive, system calls [6]
[1]
gopher://gopher.conman.org/0Phlog:2012/01/26.1
[2]
http://en.wikipedia.org/wiki/Closure_(computer_science)
[3]
http://www.lua.org/
[4]
http://www.c2.com/cgi/wiki?LexicalScoping
[5]
gopher://gopher.conman.org/0Phlog:2012/01/26.1
[6]
gopher://gopher.conman.org/0Phlog:2012/01/28.1
Email author at
[email protected]