In one of the projects I'm currently working on, Lua is used a lot as a data description language. As a result, there are many occasions where I'd like to run a switch statement work over a Lua string. One example of this is the following function:
"Line\0Stuff" will result in a LineArt rather than an UnknownArt, but usually this is acceptable. A further refinement might also make use of the string length:memcmp rather than strcmp. However, compared to the very first (non-functional) code fragment, this is harder to read and harder to maintain. This point is important to bear in mind, but things will get worse still before they get better. It just so happens that in the project I'm working on, the Lua library is statically linked. This means I can take advantage of Lua's implementation details safe in the knowledge that the implementation isn't going to change. The detail which I'd like to take advantage of is that Lua calculates a hash value for each string, and stores this in a header prior to the string contents. It also stores the length in this header, which we can also take advantage of. This train of thought leads to the following code fragment:strcmp, this version isn't perfect. It is highly likely (at least for strings longer than 4 characters) that there will be some other strings of the same length and hash value, but this is acceptable to me. On the positive side, this version should be extremely quick, as switching over a hash should be faster than sequential memcmps. Unfortunately, not only is this version unreadable and unmaintainable, it is also unwritable.
At this point, enter code generation. It is an entirely mechanical process to translate the original (non-functional) code into hash-based dispatch code, and furthermore the hash calculations are best done by a machine. Therefore I've written a preprocessing script for C++ source files which performs this translation. The input looks almost like the original (non-functional) code, with the addition of some markers:
#ifdef LUA_STRING_SWITCH, throws away any existing #else block, and then writes an #else block based on the contents of the switch, resulting in something like:LUA_STRING_SWITCH isn't defined, and so the hash-based dispatch gets used. At edit time, I use the folding features of an IDE to hide the nasty hash-based dispatch, so all I see is:Introduction to simple iterators in Lua
Let us begin by considering what a simple iterator is. In Lua, a simple iterator is a function. Each time you call the function, you get back the next value in the sequence. In the following example, f is (assumed to be) a simple iterator:
string.gmatch returns a simple iterator, but it is questionable whether or not this is mandated by the language. In particular, LuaJIT returns a full iterator rather than a simple iterator; see later]
As Lua functions can return multiple values, it seems logical to allow iterators to produce multiple values per call, and this is indeed allowed. In the following example, f is (assumed to be) a simple iterator which produces two values per call:
To signal that it has finished producing values, an iterator returns nil. Well, nearly; an iterator can signal completion by returning no values, by returning a single nil, or by returning multiple values with the first value being nil. With this in mind, the previous example can be rewritten to use a loop rather than an explicit number of calls to f:
for loop can be used to achieve the same effect:string.gmatch is termed a simple iterator factory, as it returns a simple iterator (f). Equipped with this knowledge of how simple iterators work, we can write a simple iterator factory which emulates the numeric for loop:Introduction to full iterators in Lua
Looking at range in slightly more detail, we see that every time it is called, it returns a function, and that the function has three upvalues (init, limit, and step). From an esoteric efficiency point of view, it would be nice to have less upvalues (or ideally no upvalues at all). Full iterators are one way of achieving this. Whereas a simple iterator is just a function (f), a full iterator is a three-tuple (f,s,v). As with a simple iterator, f is still a function (or something with a __call metamethod). As for the two new bits, s is an opaque value which is passed as the first parameter to each call of f, and v is an opaque value which is passed as the second parameter to the first call of f. Subsequent calls of f pass the first return value from the previous call of f as the the second parameter.
Written out formally like that, full iterators sound a little bit odd, but once you've wrapped your head around it, they are really quite reasonable. As an example, let us rewrite range to be a full iterator factory rather than a simple iterator factory. For this, we'll take s to be limit, and v to be init - step, like so:
for loop is designed to work with full iterators, this version of range can be used just like the previous version:Looking at this version of range, the returned function only has one upvalue (step). In real terms, this means that 32 less bytes of space are allocated on the heap as compared to the three upvalue version. Admittedly this isn't much, and it hardly justifies the language support for full iterators. Rather more convincing are the pairs and ipairs full iterator factories from the Lua standard library. The full iterator machinery is precisely what these two functions need in order for their iterator functions to have no upvalues at all, meaning that you can iterate through a table without having to allocate anything on the heap, as in the following example:
map function:map function for Lua iterators might be:ConcatMapping Lua iterators
Jumping back to Haskell again, consider the slightly more complex concatMap function:
map function in Lua:map still permits the previous example:coroutine.yield for each additional tuple:Suppose we want to create a C++ std::string object, and we know how long the resulting string will be, and we know how we'll generate the content of the string, but we do not have a copy of said content in memory. As a concrete example, consider taking a block of memory, and returning a string whose content is the hexadecimal representation of that memory block. The result should satisfy the following tests:
std::stringstream tool is used, which may be slow due to be extremely flexible, and also due to not knowing how long its result will be. Given that we do not need most of the flexibility of std::stringstream, and we know how long the result will be (2 for hexifyChar, and 2 * len for hexify), we should expect to be able to do better.
As we want to construct a std::string, let us look at its constructors, and see which ones might work for us:
string ();string (const string& str);string (const string& str, size_t pos, size_t n = npos);string (const char * s, size_t n);string (const char * s);string (size_t n, char c);template<class Iterator> string (Iterator begin, Iterator end);None of these look particularly like what we want, but the last option might be viable if we can wrap a hexifying algorithm inside an iterator. If said iterator is infact a random access iterator, then the constructor will be able to obtain the length of the result before it starts fetching the individual characters.
Writing an STL-compatible iterator usually takes a lot of code, but we can use boost::iterator_facade to do most of the work for us, giving us the following code:
Just over a year ago, I looked at Lua 5.2 (work 3). Lua evolves slowly, and 5.2 still isn't quite finished, though perhaps it will be by the time the Lua Workshop 2011 rolls round in September (at which I hope to give a talk). In the mean time, Lua 5.2 (beta rc2) has been released, and this time I've identified the changes since 5.1 by annotating the new reference manual with them: An Annotated Lua 5.2 (beta rc2) Reference Manual.
Presenting the changes inline with the reference manual, as compared to just listing them, provides more context for the changes, as well as making things easier to consume by reducing the density of new information. If you have any good ideas for other ways of presenting this change information, then get in touch.
The foreign function interface (FFI) present in the latest beta releases of LuaJIT is really nice for when you need to do things outside the Lua world. At runtime you pass it some C function definitions, and then everything you've defined becomes callable, and these calls are subsequently JIT compiled in the most efficient way possible. For example, we can define and then call some Windows API functions:
This is fine and dandy for calling C from Lua, but things get rather more complicated with callbacks from C back to Lua. For example, the Windows EnumChildWindows function accepts a callback, which gets calls for every child of the given window. LuaJIT will happily accept and understand the definition of this function:
EnumChildWindows using the traditional (slow) Lua C API. On the other hand, if you're feeling foolhardy, then you can fight the FFI to get callbacks working, and do so without resorting to any external C code. Naturally, this is what we'll do.
Recent comments
2 weeks 1 day ago
2 weeks 2 days ago
2 weeks 5 days ago
18 weeks 2 days ago
23 weeks 5 days ago
24 weeks 17 hours ago
24 weeks 17 hours ago
26 weeks 1 day ago
29 weeks 2 days ago
32 weeks 4 hours ago