David Manura |
|
There are Lua wiki pages and projects I've been involved in.
Code and Projects:
checkglobals function is an alternative to etc/strict.lua and luac -p -l - | lua test/globals.lua.
General Topics, Patterns, Tricks, and Design:
module function
nil not being explicitly stored in tables
function() ... end less verbose
o:f() v.s. o.f()
Comments/Annotations on Other Documents:
This is my list of issues in Lua that should be addressed in future Lua versions (e.g. 5.2) or modules.
* Lua is in need of standard but optional interface to non-ANSI C functionality. I agree with the ExtensionProposal effort, which intends to standardize a set of useful extension functions for functionality not available via ANSI C (which the Lua core is restricted to). Real programs often need non-ANSI functionality, so why not standardize that functionality to the extent that it can be standardized?
* It is possible to crash Lua by sending bad input to some functions (e.g. os.date) that directly pass their input to certain C API functions, even ones with non-ANSI extensions. This seems contrary to Lua's presumed design goal that Lua space (unlike C space) is safe from crashing, particularly for use in sandboxing. See LuaList:2007-04/msg00511.html .
* The Lua 5.1 module system has some ugly and unnecessary behavior in its implementation of the module function (and even more-so with package.seeall). I think the module function should be avoided when writing modules--see LuaModuleFunctionCritiqued.
* The inability to incorporate statements inside expressions limits the expressibility of Lua. Well, technically you can do this via an anonymous function, but allocating anonymous functions as such is not as speed efficient (nor is Lua's syntax for it as syntactically concise). This can be useful in metaprogramming, and Metalua recognizes this (see "Statements in expressions" in the Metalua Manual) and extends the Lua parser/compiler to allow it while requiring no change to the Lua VM. See also the "let" statements mentioned below on this page and "Stored Expressions" in LuaDesignPatterns.
* The highly dynamic nature of Lua limits its performance. True, Lua is fast, but it could be faster. For example, x*x is generally faster than x^2 since Lua cannot reduce the latter to the former at compile time (think: x might have a __pow metamethod). Macro processing could alleviate this (e.g. "transforming "y = SQUARE(x+y) + 1" into "y = (let t1 = x+y in t*t) + 1"). See also LuaJIT.
* A Lua table cannot fully impersonate another Lua table, thereby limiting abstraction. For example, there is no metamethod for redefining the # operator. See GeneralizedPairsAndIpairs.
* A Lua table cannot impersonate a file handle (or stream). For example, you may have a function that writes to a given file object. You might want to pass to that function not a real file object but an object with the same interface as a file object and having an implementation that does something else (e.g. appends to a string buffer). One use of this is would be to redirect standard output not to a file but rather to a text box in a GUI. This might be accomplished with new metamethods for file access (e.g. __read and __write).
* The level parameter used in the error function lacks maintainability since a function might be called from different levels and those levels might be refactored. See LuaCarp for some effort to improve this.
* Manipulations with ... are fairly limited unless you copy it in a table (not as efficient). See also VarargTheSecondClassCitizen.
* Constant folding should not be eliminated in Lua 5.2 (there was some discussion that Roberto was considering eliminating this). It's much nicer to write x = y * (2/3) than write x = 0.66666666666666666666 and not worry about the former being slower in performance critical code.
* Definition of anonymous functions is verbose: function(x) return x^2 end v.s. || x^2 a la Metalua. This comment comes up fairly regularly. This issue is one impetus for the "Stringified Anonymous Functions" in LuaDesignPatterns. Literals in Lua generally use short symbols for their definition (e.g. {} for tables and "" for strings), so why not have this be similar for functions? There are cases in data definition particularly where we want to avoid verbose syntax (e.g. see "Local Namespaces for Data Definition" in LuaDesignPatterns).
* There is much need for a more standard way to document Lua modules. Perl has POD, and that was proposed in Lua in LuaSearch, but it hasn't yet catched on. Natural Docs has some benefits but requires some patches and has some questions of its own[3]. The benefits of these two documentation formats is that they are language neutral. (I have more to say on this.) Some want Python-like docstrings queryable at runtime though (see "Decorators, Annotators and Docstrings" in LuaDesignPatterns).
* Resource Acquisition is Initialization (RAII)[4] capabilities would be useful. Examples: enclosing file handles to release locks, releasing a database lock, or even things like function x() local trace = Trace("x"); ... end where trace prints a log message on creation and destruction (i.e. function entrance and exit).
* Fix the lua51.dll v.s. lua5.1.dll inconsistency in LuaBinaries / Win32. See LuaProxyDllTwo.
* for _,v in ipairs(t) is ugly, with the main complaint is that the meaning is not immediately apparent to users less familiar with Lua (Lua users can get used to it). Could for k,v in t be made shorthand for for k,v in pairs(t), at least is some cases?
* Is there an efficient (O(1)) way to remove all elements from a table without changing the identity of the table (e.g. by allocating a new table)? Is this important? Would it be useful to provide a function in Lua that preallocates an array of size N (like lua_createtable)?
* A main complaint about Lua is a lack of consistency and centralization for Lua modules--in terms of locating, installing, documenting, testing, dependency tracking, etc. Think: Perl's CPAN. Others have noted this too [5]. [LuaForge] is part of the solution. [LuaRocks] may be part of the solution too. I believe that LuaSearch can be another part of the solution on the documentation/search side. This wiki is likely part of the solution. Lua may not have quite the set of libraries that Perl or Python has. However, an interesting opportunity is to expose the Python libraries into Lua via LunaticPython--instantly, Lua acquires the vast resources of the Python developer community. (Maybe the same may be done with Perl.) Making this seamless for the end-user could go a long way.
The following are recommendations or what I think are good practices for this wiki.
(1) All code or pages should be marked with the Lua version it is intended to run on.
One example:
-- Compatible with Lua 5.1 (not 5.0). function test(t) print(t, # t) end
A problem in the past was that people added Lua 4 examples to the wiki. Then Lua 5.0 followed by 5.1 came along, which often fails to recognize Lua 4 (and even sometimes Lua 5.0). However, the Lua 4 code remained on the wiki, and there was no hint of this to the reader. Asko agrees [6]. Marking the version as such will do much to solve the problem. In fact, this is already enforced on LuaPowerPatches. Also, if you find old code but don't have time at the moment to fit it, I recommend marking it with a VersionNotice.
Ideally, we'd want old Lua code on the wiki converted to the latest version of Lua. Still, I think it is ok, maybe desirable, to keep the old version as a footnote for historical reference. Just mark it as such.
(2) Proper syntax highlighting of interactive Lua sessions would be useful, as this occurs a lot on the wiki. You can use regular "Lua" syntax highlighting, which usually works ok but not always:
> = "test if [[" test if [[ > = "test]]" test]]
One version of the Perl code used by the wiki is at LuaToHtml. I'd like to offer a patch, but see comments there.
(3) Syntax highlighting for C.
This would help in the many C code examples. Requested also by RiciLake on GuestBook.
(4) Style recommendations for authoring pages
Based on editing a lot of pages, these are what I think are good practices for authors and editors to follow. Use the Lua syntax highlighting feature. Indent code examples to the right (as done in the Lua examples above) to set them off from the surrounding text. Avoid tabs, but rather use two spaces (or three), as follows the Lua Manual and PiL book style, and as I think is most suitable for the wiki medium. Avoid extra spaces in expressions as in x = f( x, y ) or { a , b } but rather use x = f(x, y) or {a, b}--in general use the most conventional style consistent with other pages on the wiki. Actually, I just found this: SourceCodeFormatter.
Some sets of pages are sufficiently similar in nature that they fall into certain classes, in which case some consistency can be imposed. One such example is SampleCode.
(5) Structure of the wiki
Some past comments on the overall wiki structure are in WikiStructure, but I'm still forming an opinion about the overall structure, and for now a higher priority is a review most of the wiki content as noted below.
(6) Periodic review of content.
Content on the wiki should be periodically reviewed for quality assurance, consistency, and correctness of content. As Lua changes and the Lua community changes, published content can become less correct over time (as in the Lua 4 case above shows). I'm currently working on my own review of much of the wiki content.
My favorite language in general is Perl, particularly some of the organized software engineering practices followed on CPAN, but Lua provides a lot with very little and is more optimal in certain situations (see LuaVersusPerl), and C/C++ is more optimal in other situations requiring good optimizing compilers, static type checking for large programs, and access to the OS (in fact, Lua + C/C++ provides a good combination for certain programs). C/C++ lacks innovation due to standards compliance and language complexity (e.g. writing a C++ source code analyzer, and consider the tons of macros in the Lua source), and some of its complexities like template metaprogramming get out of control, but see D and Boost. Java is fast, the language is mature and has very good libraries, but it has a large footprint and the language is verbose and only slowly recognizing the need for paradigms other than the standard OO model; scripting languages implemented in the JavaVM should be encouraged such as Jython, and there's even some work on a version of Lua that compiles into Java bytecode. Python and related languages are ok, but whether they provides real improvement over Perl (the language plus the community) is debatable. Haskell, Ocaml, and Scheme should be explored, but they are more specialty languages (e.g. some of the major projects developed in Haskell, such as Darcs, have a large memory footprint).
(add here)