mailto:john@neggie.net
Lua-user, man behind the wiki curtain. (Challenge: say "lua-users" ten times fast.)
I've influenced Lua by successful lobbying for:
Presentations / publications
My Pages (or at least pages I started)
My posts to lua-l [1]
Favorite lua-users wiki pages
lua-users.org is...
I think Python PEP's [3] are a great source of info. Find out where Python was flawed and how it's being fixed. Learn about Python's implementations of the latest language fads.
I'd like to mention a wonderful property of (most) wiki implementations that may not be entirely obvious. They forget the past. Although an edit history is maintained for each page, it fades out over time. So deleted mistakes, unkind words, and useless material really disappear unless someone explicitly acts to revive or archive them. This is quite a different concept from the mailing list or newsgroup where, in the case of a public forum, every word may likely be archived until the end of civilization. An interesting article related to this subject is In Defense of the DELETE
Key [4].
Here's how to use the unix wget
command to make a static copy of this wiki for offline browsing. Of course you can't edit or search the wiki when offline, so that takes the fun out of things.
wget --mirror --html-extension --convert-links http://lua-users.org/wiki/
JOHN'S LUA WARTS
These points are serious and if not fixed eventually (I'm fairly patient) I'd consider starting a Lua derivative that implements them:
- Table constructors drop sequence length information. When a table is defined by a table constructor (e.g. { x = 10; 'foo', 5, bar() }, the length of the list part-- known by the core when it constructs the table-- is discarded. The length operator (#) can correctly deduce it afterwards, but only if there were no nil values in the sequence. (As somewhat clunky solution,
table.pack
in Lua 5.2 will cover sequence-only tables.)
- No efficient and concise list iteration. The "
for i=1,getn(t)
" idiom is verbose and when used carelessly requires a global table lookup per item. The foreachi
idiom is not efficient due to extra function call overhead per item, and not concise due to the need to define a function object. I have implemented a new for
construct as a solution, see LuaPowerPatches. (As of Lua 5.1, the idoms have changed but the issue still stands. We now have "for i=1,#t
" or "for _,item in ipairs(t)
".)
These points are ugly but tolerable:
- Indexing from 1 and use of closed ranges. Indexing from 1 is contrary to the most-used languages and argued against succinctly by Dijkstra [5]. In Lua, closed ranges are used in the "for" construct and library functions, with the uncomfortable (n, n-1) meaning zero length. Index adjustments of +/-1 are often required in normal code. (See CountingFromOne.)
- List operations do not support nil elements. The # operator and functions which depend on it such as unpack and ipairs are non-deterministic should a list contain a nil element, or else simply ignore trailing nils. Nil is a useful value, and reasonable behavior of this fundamental data type should not be obstructed by Lua's table implementation of it. (Roberto has admitted that nil is not a first class value because of this issue.) This limitation would be fairly straightforward to work around if table constructors did not drop sequence length information (see above).
- Lua core and standard libraries do not enumerate exceptions. The set of errors which can be raised by the Lua core and standard libraries are not enumerated. If an application wants to catch a specific error, it must employ the fragile practice of parsing exception strings.
- BTW, more generally perhaps "traceback reform" on my page. For example, Lua concatenates file paths with string exceptions and even truncates those file paths. --DavidManura
Historical warts which have been resolved:
- Global scope is treated specially. Although the global scope can be treated as a normal table in many respects, user-defined events are handled differently. (Fixed in Lua 5.0.) For example the following lines call different assignment events:
a = 5
globals().a = 5
- No lexical scoping. The upvalue feature used with tables provides a form of lexical scoping, but only for the case of accessing the next higher scope. (Fixed in Lua 5.0.)
- No user-defined iteration. The lack of hooks for user-defined iteration prevents us from making useful proxy tables and lists. (Fixed in Lua 5.0.)
- Value nil used for false. It's not possible to distinguish between a non-existant variable and a variable assigned from a boolean expression. (See BooleanTypeProposal. Fixed in Lua 5.0.)
- Poor type control in implementation. Implementation does not provide compile options for (complete) control of C type useage. For example double and long types are referenced extensively causing problems for certain platforms. (Much improved starting with Lua 5.0.)
- Cannot override length operator (#) on tables or strings. Most notably in the case of tables, this obstructs the creation of custom list-like objects from Lua code. (Fixed-- at least for tables-- in Lua 5.2.)
-
lua_tostring
does not honor __tostring
metatable hook. lua_tostring
in the C API and tostring
in the base Lua library are not equivalent. The former does not honor the __tostring
hook, which is important for debug and error output of user defined types, and in general the emulation of strings with user types. As an example of the problem, the lua
command line interpreter uses lua_tostring
in the case of uncaught exceptions, leaving no way to communicate the details of non-string exception objects to the user. (In Lua 5.2 there is a separate function luaL_tolstring
which honors __tostring
, and interpreter exception handler appears to use this.)
-
string.format
%s does not invoke tostring
. (Fixed in Lua 5.2.)
- No scope hook metamechanism. Many applications expose scarce resources to the scripting environment such as locks; handles for files, memory, and database transactions; etc. Such resources need to be released promptly and deterministically after use, and despite any exceptional condition in the program. Moreover, Python's context managers (`with` statement) demonstrate endless uses for such a feature. Of course this can be accomplished with Lua as it is, but the resulting code is hard to follow, highly error prone, and makes heavy use of protected calls-- limiting potential use of coroutines. This could be resolved if Lua provided a way to hook into scope exit events. See [Lua: Improving deterministic resource cleanup]. (Covered by Lua 5.4 "to-be-closed" variables.)
RecentChanges · preferences
edit · history
Last edited September 17, 2022 6:47 am GMT (diff)