Peter Shook |
|
I'm a C/Awk/Perl hacker who wasn't very pleased with Perl's large list of obscure functions and macros know as XS. That and Perl's megaton size made me switch to Lua. Although Perl's extension tools and documentation have improved since I switched to Lua, I won't go back to Perl simply because Lua is truly a joy to use.
Lua can handle hex numbers with the tonumber
function, but my fellow engineers are more comfortable with C's 0x syntax so I made this patch for them.
This patch is for 5.0 but it is so simple, you can easily get it to work with older versions of Lua. lua-5.1-alpha version [2]
$ lua Lua 5.0 Copyright (C) 1994-2003 Tecgraf, PUC-Rio > = 0x10 16 > = 0x100 256 > function hex(n) >> return tonumber(n,16) >> end > > = 0xff == hex'FF' true >
This patch adds chdir
, opendir
and stat
to the os
table.
It works on Linux, Cygwin and Mingwin.
For those who dislike typing self.member
all the time, here is a version of
[lauxlib.c]
that changes luaL_loadfile
and luaL_loadbuffer
to substitute
@somename
for self.somename
and @somemethod(...)
for self:somemethod(...)
.
You can also use #
for comments.
List = setmetatable({}, {__index = table}) List.__index = List function List:new(...) return setmetatable(arg, self) end function List:push(x) @insert(x) return self end function List:pop() return @remove() end function List:shift() return @remove(1) end function List:append(list) for _,elem in ipairs(list) do @insert(elem) end return self end function List:fun(a, b) @a = a @b = b return @n end x = List:new(1, 2, 5) x:foreachi(print) x:push(99) print(x:concat', ') print('fun', x:fun('one', 'two'), x:shift()) x:foreach(print)
$ lua eg.lua 1 1 2 2 3 5 1, 2, 5, 99 fun 4 1 1 2 2 5 3 99 a one b two n 3
Those with a Python or PHP background probably prefer variables within
functions to be local by default. This is easily done in Lua 5.0 by
using the newindex
event to give functions a new environment
when they are stored in the package.
For example:
local Pkg = {} local function fixfuncs(env, name, value) rawset(env, name, value) if type(value)=='function' then print('newfunction', env, name, value) setfenv(value, setmetatable({}, {__index=env})) end end setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newindex=fixfuncs})) y = 0 function one(x) y = x return y end function two() Pkg.y = 99 y = 2 return y end local function three() y = 3 return y end print(y, one(1), y, two(), y, three(), y)
$ lua test1.lua newfunction table: 0xa0459f0 one function: 0xa046ab8 newfunction table: 0xa0459f0 two function: 0xa0466d8 0 1 0 2 99 3 3
Pkg.
or _G.
.
The newindex
event won't work on local functions,
but if you're not a Perl programmer you probably don't care.
What if you wanted to magically alter the function environments
for local function too?
Here is a dubious patch that adds newfunction
and newtable
events.
The metamethod for the newfunction
event is called whenever a function
is created in an environment with a __newfunction
key in its metatable.
We can rewrite the previous example like so:
local Pkg = {} local function fixfuncs(env, f) print('newfunction', env, f) setfenv(f, setmetatable({}, {__index=env})) end setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newfunction=fixfuncs})) y = 0 function one(x) y = x return y end function two() Pkg.y = 99 y = 2 return y end local function three() y = 3 return y end print(y, one(1), y, two(), y, three(), y)
three
's y
variable is local.
$ lua test2.lua newfunction table: 0xa0459f0 function: 0xa045fb0 newfunction table: 0xa0459f0 function: 0xa046478 newfunction table: 0xa0459f0 function: 0xa040730 0 1 0 2 99 3 99
This patch changes the semantics of object:method()
to use a new and separate self
event instead of the usual index
event.
This lets you add some class to your tables, and still leaves the index
event free for other uses.
local Pkg = {} local function fixtable(env, t) print('newtable', env, t) setmetatable(t, {__self=table}) end setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newtable=fixtable})) t = { 'one', 'two', 'three' } print(t:concat'/', t:getn(), t:remove(1), t:remove(), t:getn())
$ lua test3.lua newtable table: 0xa0459f0 table: 0xa045f98 one/two/three 3 one three 1
$ src/lua Lua 5.1 (alpha) Copyright (C) 1994-2005 Lua.org, PUC-Rio > write from io > format from string > > function printf(...) write(format(...)) end > > printf("I should have written this patch %d years ago\n", 2) I should have written this patch 2 years ago >
Here is a basic version of the patch that uses the existing keyword in
instead of from
[8]