Showing posts with label Lua. Show all posts
Showing posts with label Lua. Show all posts

Sunday, 31 May 2015

What can C++ Libraries Learn from Lua?

The Convenience of Text Pattern Matching

const char *text = "Some people, when confronted with a problem, think \"I know, I'll use regular expressions.\". Now they have two problems.";

(Example for std::regex from http://http://en.cppreference.com/w/cpp/regex)

Parsing text with Regular Expressions is a powerful technique traditionally available with so-called 'scripting' languages, from the grand-daddy Awk through Perl onwards. Regular expressions are first-class citizens of these languages and their users get adept at using them. Of course, there can be too much of a good thing, and sometimes those users forget that they have perfectly good if-statements for making complex matches easier to write and read. This is why I like Lua string patterns precisely because they are more limited in scope. Strictly speaking, although similar, they aren't regular expressions since they lack the 'alternation' operator |. But they are a good balance between simplicity and power, which is the global virtue of Lua, together with smallness. (Lua in total weighs less than the PCRE library.)

C++ and its older brother C are not very good at text manipulation, by the standards set by these dynamic languages. So this investigation is about how we can use regular expressions for text wrangling, first in C and then in C++, and how the standard ways can be improved. My method will simply be to use the Lua string functions as a design template, whenever appropriate.

The C Way

For some obvious reasons, regular expressions are not so easy to use in C, although part of the POSIX standard and thus always available on compliant systems. There is no equivalent to regexp literals (/..../) so you have to compile the expression explicitly before you use it. You must also create a buffer to receive the positions where the match and its submatches occured in the string.

 regex_t rx;
 regmatch_t matches[1];  // there's always one match
 regcomp(&rx,"[[:alpha:]]+",REG_EXTENDED);

 if (regexec(&rx,"*aba!",1,matches,0) == 0) {
     printf("regexec %d %d\n",matches[0].rm_so,matches[0].rm_eo);
 } else {
     printf("regexec no match\n");
 }
 ...
 // explicitly dispose of the compiled regex
 regfree(&rx);

Doing something more realistic that just matching is a more involved. Say we wish to go over all the word matches with length greater than six in the above useful quotation:

 const char *P = text;
 char buffer[256];  // words are usually smaller than this ;)
 while (regexec(&rx,P,1,matches,0) == 0) {
     int start = matches[0].rm_so, end = matches[0].rm_eo;
     int len = end-start;
     if (len > 6) {
         strncpy(buffer,P+start, len);
         buffer[len] = 0;
         printf("got %d '%s'\n",len,buffer);
     }
     P += end; // find the next match
 }

Contrast with the Lua solution - note how '%' is used instead of '\' in regular expressions, with the character class '%a' meaning any char in the alphabet:

 for word in text:gmatch('%a+') do
     if #word > 6 then
         print ("got",#word,word)
     end
 end

So clearly there is room for improvement!

A Higher-level C Wrapper

I am not alone in finding classical regexp notation painful, especially in C strings where the backslash is the escape character. E.g. if we wanted to use special characters literally: "\$\(([[:alpha]]+\))". The Lua notation for this expression would simply be "%$%(%a+)%)" which is easier on the eyes and the fingers. So I've provided an option to rx_new to convert Lua notation into classical notation. It is a very simple-minded translation: '%' becomes '\', '%%' becomes '%', and the Lua character classes 's','d','x','a','w' become the POSIX character classes 'space', 'digit', 'xdigit','alpha' and 'alnum' within brackets like '[[:space:]]'. The semantics are not at all changed - these regexps only look like Lua string patterns, although mostly equivalent.

An optional POSIX-only part of llib (see rx.cin the lllib-p directory) provides a higher-level wrapper. rx_find is very much like Lua's string.find although we don't have the convenience of multiple return values.

 Regex *r = rx_new("[[:alpha:]]+",0);
 int i1=0, i2=0;
 bool res = rx_find(r,"*aba!",&i1,&i2);
 printf("%d from %d to %d\n",res,i1,i2);

 // Now find all the words!
 int start = 0,end;
 while (rx_find(r,text,&start,&end)) {
     int len = end - start;
     if (len > 6) {
         strncpy(buffer,text+start,len);
         buffer[len] = 0;
         printf("[%s]\n",buffer);
     }
     start = end;  // find the next match
 }
 ...
 // generic disposal for any llib object
 unref(r);

The need for an extra 'matches' array has disappeared and is now managed transparently by the Regex type. It's pretty much how a Lua programmer would loop over matches, if string.gmatch wasn't appropriate, except for the C string fiddlng - which is essential when you specially don't want to allocate a lot of little strings dynamically.

Here is a cleaner solution, with some extra cost.

 int j1=0,j2;
 while (rx_find(r,text,&j1,&j2)) {
     str_t word = rx_group(r,0);
     if (array_len(word) > 6) {
         printf("%s\n",word);
     }
     unref(word);
     j1 = j2;
 }

rx_group will return the indicated match as a llib-allocated C string; could have used our friend strlen but array_len is going to be faster, since the size is in the hidden header; I've put in an unref to indicate that we are allocating these strings dynamically and they won't go away by themselves.

So, some code for extracting 'NAME=VALUE' pairs in a string separated by newlines (the ever-flexible C for-loop helps with not having to do j1=j2 at the end of the loop body, where these things tend to get forgotten, leading to irritatingly endless loops.)

 Regex *pairs = rx_new("(%a+)%s*=%s*([^\n]+)",RX_LUA);
 str_t test_text = "bob=billy\njoe = Mr Bloggs";
 for (int j1=0,j2; rx_find(r,test_text,&j1,&j2), j1=j2) {
     str_t name = rx_group(r,1);
     str_t value = rx_group(r,2);
     printf("%s: '%s'\n",name,value);
     dispose(name,value);
 }

This is easier to write and read, I believe. Since the loop counters are not used in the body of the loop, and since this is C and not C++, you can write a macro:

 #define FOR_MATCH(R,text) (int i1_=0,i2_; rx_find(R,text,&i1_,&i2_; _i1=i2_)

There are also functions to do substitutions, but I'll leave that to the documentation. llib is linked statically, so using part of it incurs little cost - I'd estimate about 25Kb extra in this case. You will probably need to make normal copies of these strings - a general function to copy strings and other llib arrays to a malloc'd block is here:

 void *copy_llib_array (const void *P) {
     int n = array_len(P) + 1;   // llib always over-allocates
     int nelem = obj_elem_size(P);
     void *res = malloc(n*nelem);
     memcpy(res,P,n*nelem);
     return P;
 }

News from the C++ Standards Committee

Some may think I have anti-C++ tendencies, but a professional never hates anything useful, especially if it pays the bills. So I was interested to see that regular expression support has arrived in C++.

 #include <regex>
 using namespace std; // so sue me
 ...
 // 'text' is the Useful Quote above...
 regex self("REGULAR EXPRESSIONS",
         regex_constants::ECMAScript | regex_constants::icase);
 if (regex_search(text, self)) {
     cout << "Text contains the phrase 'regular expressions'\n";
 }

That's not too bad - the Standard supports a number of regexp dialects, and in fact ECMAScript is the default. How about looking for words longer than six characters?

 regex word_regex("(\\S+)");
 string s = text;
 auto words_begin = sregex_iterator(s.begin(), s.end(), word_regex);
 sregex_iterator words_end;

 const int N = 6;
 cout << "Words longer than " << N << " characters:\n";
 for (sregex_iterator i = words_begin; i != words_end; ++i) {
     smatch match = *i;
     string match_str = match.str();
     if (match_str.size() > N) {
         cout << "  " << match_str << '\n';
     }
 }

Perhaps not the clearest API ever approved by the Standards Committee! We can make such an iteration easier with a helper class:

class regex_matches {

 const regex& rx;
 const string& s;

public:

 regex_matches(const regex& rx, const string& s): rx(rx),s(s) {
 }
 sregex_iterator begin() { return sregex_iterator(s.begin(),s.end(),rx); }
 sregex_iterator end() { return sregex_iterator(); }
}; ....
 regex_matches m(word_regex,s);
 for (auto match : m) {
     string match_str = match.str();
     if (match_str.size() > N) {
         cout << "  " << match_str << '\n';
     }
 }

We're finally getting to the point where a straightforward intent can be expressed concisely and clearly - this isn't so far from the Lua example. And it is portable.

Substituting text according to a pattern is a powerful thing that is used all the time in languages that support it, and std::regex_replace does a classic global substitution where the replacement is a string with group references.

Alas, there are some downsides. First, this does not work with the GCC 4.8 installed on my Ubuntu machines, but does work with the GCC 4.9 I have on Windows. Second, it took seven seconds to compile simple examples on my I3 laptop, which is an order of magntitude more than I expect from programs of this size. So, in this case, the future has not arrived.

A C++ Wrapper for POSIX Regular Expressions.

Portability is currently not one of my preoccupations, so I set out to do a modern C++ wrapping of the POSIX API, in a style similar to llib-p's Regex type. (Fortunately, the GnuWin32 project has made binaries for the GNU regex implementation available - although they are only 32-bit. The straight zip downloads are what you want, otherwise you will probably have unwelcome visistors on your machine.)

When testing this library on large-ish data, I received a shock. My favourite corpus is The Adventures of Sherlock Holmes from the Gutenberg project; just over 100,000 words, and this regexp library (from glibc) performs miserably to do something that is practically instantaneous in Lua. (std::regex is much better in this department.) So I've taken the trouble to extract the actual Lua pattern machinery and make it available directly from C++.

Let me jump immediately to the words-larger-than-six example. It is deliberately desiged to look like the Lua example:

 Rxp words("%a+",Rx::lua);  // simple Lua-style regexps
 for (auto M:  words.gmatch(text)) {
     if (M[0].size() > 6)
         cout << M[0] << "\n";
 }

When modern C++ cooks, it cooks. auto is a short word that can alias complicated types - (here just Rx::match), but the range-based for-loop is the best thing since std::string. And I've got my order-of-magnitude smaller compile time back, which is not an insignificant consideration.

(if you want to use the Lua engine, then replace the first declaration with simply Rxl words("%a+").)

I resisted the temptation to provide a split method; heaven knows the idea is useful but doesn't have to be implemented that way. It would return some concrete type like vector<string> and it would introduce a standard library dependency other than std::string into the library. Rather, Rx::match has a template method append_to which will take the results of the above iteration and use push_back on the passed container:

 vector<string> strings;
 words.gmatch(text).append_to(strings);

If you wanted a list<string> instead, then it trivially happens. You can append to a container and so forth without awkward splicing.

What would it mean to populate a map with matches? I don't think there's one answer, since there is no clear mapping, but here is one way of interpreting it; the expresson must have at least two submatches,and the first will be the key, and the second will be the value:

 Rx word_pairs("(%a+)=([^;]+)",Rx::lua);
 map<string,string> config;
 string test = "dog=juno;owner=angela"
 word_pairs.gmatch(test).fill_map(config);

Again, this will work with any smart array, not just std::map, as long as it follows the standard and defines mapped_type. The user of the class only pays for this method if it is used. These are considerations dear to the C++ mindset.

I'm an admirer of Lua's string.gsub, where the replacement can be three things:

  • a string like '%1=%2', where the digits refer to the 'captured' group (0 is the whole match)
  • a lookup table for the match
  • a function that receives all the matches

The first case is the most useful. Here we have a match, where the submatch is the text we want to extract (called 'captures' in Lua.)

 Rx angles("<(%a+)>",Rx::lua);
 auto S = "hah <hello> you, hello <dolly> yes!";
 cout << angles.gsub(S,"[%1]") << endl;
 // --> hah [hello] you, hello [dolly] yes!

With the second case, I did not want to hardwire std::map but defined gsub as a template method applicable to any associative array.

 map<string,string> lookup = {
    {"bonzo","BONZO"},
    {"dog","DOG"}
 };
 Rx dollar("%$(%a+)",Rx::lua);
 string res = dollar.gsub("$bonzo is here, $dog! Look sharp!",lookup);
 // --> BONZO is here, DOG! Look sharp!

Forcing the third 'callable' case to overload correctly doesn't seem possible, so it has a distinct name:

 // we need a 'safe' getenv - use a lambda!
 res = dollar.gsub_fun("$HOME and $PATH",[](const Rx::match& m) {
     auto res = getenv(m[1].c_str());
     return res ? res : "";
 });
 // --> /home/user and /home/user/bin:/....

(One of the ways that GCC 4.9 makes life better is that generic lambdas can be written, and the argument type here just becomes auto&.)

In this way, string manipulation with regular expressions can be just as expressive in C++ as in Lua, or any other language with string pattern support.

The files (plus some 'tests') are available here, but remember this is very fresh stuff - currently in the 'working prototype' phase.

Transferable Design

The larger point here is that dynamically-typed languages can provide design lessons for statically-typed languages. C++ and C (particularly) are poor at string manipulation compared to these languages, but there is nothing special here about dynamic vs static: it is a question of designing libraries around known good practices in the 'scripting' universe and using them to make programming more fun and productive in C and C++.

There is a limit to how far one can go in C, but it's clear we can do better, even if llib itself might not feel like the solution. C is not good at 'internal' iterators since function pointers are awkward to use, and so 'external' iterators - using a loop - is better for custom subtitutions, etc.

C++ has already got a standard for regular expressions, but it will take a while for the world to catch up: we are being hammered here by heavy use of templates, all in headers. This is of course a classic example of too much of a good thing, because generic code is how C++ escapes the tyranny of type hierarchies, by compile-time static duck-typing. (The fancy word here is 'structural typing'.) For instance, Rxp::gsub can use anything that looks like a standard map.

Even there, I wanted to present an alternative design, not necessarily because I want you to use it, but because looking at alternatives is good mental exercise. The Standard is not Holy Scripture, and some parts of it aren't really ready, in a pragmatically useful way. In the comfort of our own company repository I can choose a solution that does not damage our productivity.

Monday, 12 August 2013

A Question of Notation: Revisiting Moonscript

Growing Up Nicely

Since the last time I reviewed Moonscript here it has matured nicely in ways that make it easier to use. Some nasty gotchas (like a[i-1] being misinterpreted) have gone away and there is better error reporting.

It has found its way into my toolbox for quick utilities and prototypes that I don't need to share with others. (That may change; my colleagues know Python, not Lua, and I suspect that they will find Moonscript easier to read.)

I hope to make the point that even people who use Lua and don't wish to bet on an 'experimental' language can benefit from learning a little Moonscript, since it makes an excellent notation for expressing Lua programs. In particular, its terse syntax is well suited to interactive exploration.

Get Interactive

Out of the box, there is no REPL, but writing a sufficiently-good one was not difficult. mooni was the result. It does not try to solve the tricky problem of when to start a block; you indicate this by ending a line with a backslash.

moon-article$ mooni
MoonScript version 0.2.3
Note: use backslash at line end to start a block
> ls = {10,20,30}
> ls
{10,20,30}
> m = one:1, two:2
> m
{one:1,two:2}
> for x in *ls \
>>  print x
>>
10
20
30

Moonscript works with tables in the same way as Lua, except that the more conventional colon is used for associative key-value pairs. You don't always have to use curly brackets for map-like tables (e.g. the assignment to m above). Since all statements in Moonscript can have a value, we don't need any special way to indicate that a expression is being evaluated. mooni also does pretty-printing of tables.

A language with no libraries is a no-starter, but a language which is essentially a new notation for an existing language starts off with a ecosystem. For instance, we have Penlight available.

> require 'pl'
true
> utils.split 'one two three'
{"one","two","three"}
> utils.printf "hello '%s'\n", 'world'
hello 'world'
> utils.import math
> cos(pi/8) + sin(pi/2)
1.9238795325113

Function calls don't need parentheses, except when you need to force a function call to bind with an argument - in that case, the opening paren must not be separated by space from the function. (A more formal way of stating Moonscript's semantics here is that the call operator has a much lower precedence)

This sensitivity to whitespace takes a little getting used to, since Lua has practically none, but the payoff is that most function calls require fewer keystrokes, which matters in interactive mode.

The first great thing about an interactive mode is that the beginner has a chance to try statements out one by one, and gets their rewards ('it works!') and punishments ('why did that not work?') in little incremental steps.

The second great thing comes from the fact that we are often beginners; testing out a new library, exploring an API, trying out one-liners before inserting them into thousand-line programs, etc. So even if you are a Lua programmer, using a Moonscript REPL will allow you to experiment with your Lua modules in a less tedious way.

The function notation is very compact, which makes a functional style more pleasant:

> -- 'return' is implicit here
> sqr = (x) -> x^2
> sqr 10
100
> -- functions of no arguments do not need argument lists
> f = -> 42
> f()
42
> add = (x,y) -> x + y
> -- partial application
> add1 = (x) -> add x, 1
> add1 10
11
> ls = List{'alpha','beta','gamma'}
> -- mapping a function over a Penlight list
> ls\map => @sub 1,1
{a,b,g}
> ls\filter => #@ > 4
{alpha,gamma}

The fat arrow is short for a function with an implicit self; @ is a shorthand for self.

Everything is a Value

The use of indentation to indicate blocks is now firmly associated with Python, so people with a Python background might feel superficially at home. But consider this:

> f = -> 10,20
> {f()}
{10,20}
> if 0 then 'ok'
"ok"
> if 1 > 2 then 'ok' else 'nope'
"nope"
> ls = for i = 1,3 do i
> ls
{1,2,3}
> [i for i = 1,3]
{1,2,3}

As in Lua, functions are first-class values, and they can return multiple values. (In Python there is the illusion of multiple return values, but really they are packed into a tuple and then unpacked in any assignment, which is a lot less efficient). If such a function is evaluated as the last value in a table constructor, all the values are captured. This is all standard Lua semantics. The if construct should come as a surprise to both Lua and Python users, since it returns a value. (The gotcha for a Python user is that 0 is not false; only false and nil evaluate as false in Lua)

for statements are expressions that collect their values into a table, only if they are in an assignment context. So they don't needlessly create tables! For this simple task, list comprehensions are better, but consider this example from the manual:

doubled_evens = for i=1,20
  if i % 2 == 0
    i * 2
  else
    i

(The general rule is that the block versions of if,for and while leave out the then or do keyword. There is no end keyword!)

The with statement works like the similar statement in VB or Pascal; a dot is needed to indicate the fields that will be set within the table. And it's no surprise that it returns that table as a value:

> with {} \
>>  .a = 1
>>  .b = 2
>>
{a:1,b:2}

This gives us a really cool way to write modules, because (again) the value of loading a file is the value of the last expression.

-- util.moon
with {}
    .greeting = (name) -> print "Hello ", .quote name

    .quote = (s) -> string.format('%q',s)
----------
> u = require 'util'
> u.greeting 'Dolly'
Hello     "Dolly"

(Note how we can use the dot for reading fields as well as writing them.)

Doing Programs Bit by Bit

require in Moonscript works just like in Lua, except it will load any *.moon files on the module path as well. But require is not so useful for incremental and interactive development, because it will only load once and cache the result. Which is why we will rather use dofile for this purpose - but the global dofile from Lua and only loads Lua scripts. It is easy to make a Moonscript-aware dofile using the built-in moonscript module.

> moon = require 'moonscript'
> dofile = (x) -> assert(moon.loadfile x)()
> u = dofile 'util.moon'
> u
{greeting:function: 0xfd9610,quote:function: 0xfbc140}

So now it's possible to reload a module and try out the changes. The finger-friendly syntax makes interactive use easier. If I had a module which controlled a robot, then Moonscript provides a nice command prompt:

> turn left
> speed 2
> obstacle -> speed -2

Now this isn't such an imaginary scenario. PbLua is a Lua port for the Lego Mindstorms NXT kit, and it has a Lua prompt. Getting Moonscript to work with pbLua does not require that the micro actually runs Moonscript! A custom mooni could translate everything into plain Lua and push that up, ditto for scripts.

This point needs emphasizing - moonc compiles Moonscript to Lua. The Lua environment that then runs that code could be stock Lua 5.1, 5.2, LuaJIT or whatever. The decision to use Lua as the intermediate language has given us a lot more flexibility in applications.

In mooni, if you want to see what Lua code was generated by the last executed statement, use this common expression of puzzlement:

> t = one:1, two:2
> ?que
t = {
  one = 1,
  two = 2
}

Making up New Constructs

For instance, it seems self-evident to most people that a modern language should have syntax for exception handling. Coating Lua's pcall in some convenient sugar is very straightforward:

try = (block) ->
    ok,err = pcall block
    if not ok then err\gsub '^[^:]+:%d+: ',''
    else nil, err

test = (foo) ->
  err,val = try ->
    if foo then return 2*foo
    print a.x
  if err
    print 'error!',err
  else
    val

print test nil
--> error!  attempt to index global 'a' (a nil value)
print test 2
--> 4

There is still an issue if the function did want to return nil, but I'll leave the resolution of this to any interested parties. (hint: use select)

This kind of thing has been possible in Lua for a long time now, but people get put off by the necessity for (function() ... end) here, and anywhere where we need a lazy way to get 'lazy evaluation'.

For instance, when working with many GUI toolkits it's useful to schedule an action to be run later on the main thread. This could be expressed as later 300,-> do_something(). GUI toolkits are all about firing events; for instance in AndroLua one can create a button and attach it to an action in two lines:

@button "Please Click Me!",->
    @toast "Thanks!"

The equivalent Java code is a lesson in how boilerplate obscures otherwise straightforward code, and explains why Java simply has to get lambdas to compete.

Moonscript's syntax can play nicely in the niche established by Ruby. For instance, this is a rakefile.

task :codeGen do
  # do the code generation
end

task :compile => :codeGen do
  #do the compilation
end

task :dataLoad => :codeGen do
  # load the test data
end

task :test => [:compile, :dataLoad] do
  # run the tests
end

And here is the equivalent lakefile for Lake

-- lakefile.moon
task = target

task.codeGen nil, ->
    print 'codeGen'

task.compile 'codeGen',->
    print 'compile'

task.dataLoad 'codeGen',->
    print 'dataLoad'

task.test 'compile dataLoad',->
    print 'test'

-- without any explicit targets, lake fires this ....
default 'test'

moonc lakefile.moon would creae lakefile.lua, which lake understands. If anything, the syntax is even cleaner - I've cheated slightly by passing dependencies to the targets as space-separated strings; they can also be written as tables like {'compile','dataLoad'} which is the internal representation anyway.

Imagine a hypothetical environmental monitoring system:

rule.too_hot -> temp > 37 and humid > 80
--- handle the rule asynchronously...
If.too_hot -> print 'get them out!'

Which suggests that if I were designing a DSL (Domain Scripting Language) for such a rule-based application then my users might find Moonscript easier than plain Lua. (Embedding Moonscript in an application is not difficult, since it's mostly Lua code with dependencies on LPeg and LuaFileSystem. The Windows binary has already compiled this all into a DLL.)

Tooling and Documentation

This is something that separates the goats from the sheep when evaluating a new language. Fortunately, leaf has provided editor support - the repackaged SciTE is a good choice for Windows users. You will probably have a better experience if you edit the configuration file `Options|Open Global Options' and put these lines at the end:

split.vertical=0
open.dialog.in.file.directory=1
statusbar.visible=1

Assuming that you do want other people to use your modules, it helps to have a documentation tool that understands the language. This simple List class has basic LDoc markup. Note the use of the @within tag to put the metamethods in their own section.

The output from ldoc -f markdown -S List.moon is here.

(This is all hot off the presses so you'll have to grab from the LDoc master. I'm considering whether metamethods should automatically be put into their own section by default.)

Differences and Distinctions

Moonscript is compiled to reasonably straightforward Lua, and its detailed semantics are a superset of Lua so it finds easily into the existing Lua ecosystem. The surface syntax is different, but comes from several design choices

  • indentation is syntax - no more end
  • : for key-value pairs in tables; purely map-like tables often don't need curly brackets
  • line ends become significant, so commas are not needed in multiline tables
  • function(self,y) becomes (self,y) -> or (y) => depending on taste
  • function calls have very low precedence, hence less parens needed
  • every statement can return a value; explicit return is usually not needed
  • local-by-default means local is only needed to make scoping explicit
  • there is sugar for list comprehensions, classes and extended assignment operators like += and *=. != is a synonym for ~=

In other words, it is a determined attempt to reduce the typing needed for common operations in Lua, at the cost of more rules. This makes it a good notation for interactive work, even if your work remains mostly in Lua.

Could a person learn Moonscript without knowing Lua? No reason why not, but it will require a good self-contained tutorial and there are more syntactical gotchas. It could make a good educational language, since there you do not necessarily want a language that some of the class already know; familiarity breeds conplacency, if not actual brain damage (as Dijkstra asserted about Basic.)

Moonscript is available using LuaRocks or Windows binary - On Unix, sudo luarocks install mooni will bring in Moonscript as well, since it's a dependency. mooni itself is a single Moonscript file and can be found here.

Thursday, 5 January 2012

Building Programs with Lake

Carpenters Bitching About Tools

One of the irritating things about programming is the set of available tools for building software. A lot of the appeal of dynamic languages comes from the simple fact that you don't build, you just run. A great deal of the fuss is accidental complexity, which is Fred Brooks' term for the gap between the complexity of the task and the actual complexity of the solution.

In the begining, there was Stu Feldman's make. People have subsequently wondered what deep reason there was behind the need for tabs, but the referenced quote from The Art Of Unix Programming shows us that it was an unhappy accident:

Why the tab in column 1? Yacc was new, Lex was brand new. I hadn't tried either, so I figured this would be a good excuse to learn. After getting myself snarled up with my first stab at Lex, I just did something simple with the pattern newline-tab. It worked, it stayed. And then a few weeks later I had a user population of about a dozen, most of them friends, and I didn't want to screw up my embedded base. The rest, sadly, is history.

make is a fantastic tool, firmly in the Unix tradition of doing one thing well. It runs commands when any of their inputs are more recent than their output. Its power comes from all the other powerful little tools that come with a traditional Unix environment. (This naturally becomes an issue on Windows, where you basically have to mimic that environment closely enough, for instance MSYS.) Its pain comes from having to cope with all the weirdness of different systems, even within the POSIX world, with tools of inadequate expressiveness and power. In other words, it's a bad programming language.

There are many alternative build systems which came out of this frustration. And an entertainingly profane plea on Reddit to simply stop building new ones.

Human nature being what it is, it did not stop me. I have no particular great hopes of it gaining any fans, but Lake does provide a working example of how Lua is suited for embedded Domain Specific Languages (DSLs).

Using Lake to cope with the C

Say we have the canonical first program, hello.c. Running the lake command works as expected; there must be a lakefile:

 c.program 'hello'

and then

 $> lake
 gcc -c -O1 -Wall -MMD  hello.c
 gcc hello.o  -o hello.exe

Running lake again will give the message 'lake: up to date'. If hello.c changes (or we deleted hello.o) then things will rebuild.

This seems fairly underwhelming at first, but then we knew this was a trivial program to build in the first place. Now, if Lake finds the Microsoft command-line compiler cl.exe on the path, then it changes its tune:

 $> lake
 cl /nologo -c /O1 /WX /showIncludes  hello.c
 link /nologo hello.obj  /OUT:hello.exe

(This is what will happen on Windows if you execute Lake inside a Visual Studio command Prompt)

The whole idea about lakefiles is that they express the build on a higher level, and let the tool decide on the incantation. This is particularly useful if you aren't familiar with cl.exe, for instance.

But there is more. This simple lakefile provides:

  • cross-platform, compiler-agnostic builds (On Unix it knows to drop off the '.exe')
  • an automatically generated 'clean' target, so lake clean will do its job
  • a debug build by saying lake -g or lake DEBUG=1

I do work on embedded Linux sometimes. If I wanted my hello to work on a Gumstix then the incantation would simply be lake PREFIX=arm-linux and the correct compiler and linker would be invoked.

OK, let's get more fancy. The hello program has a second file utils.c and a shared header common.h. The lakefile now looks like this:

 c.program{'hello', src = 'hello utils'}

Please note the curly braces: program is a function of one argument, which is here a Lua table constructor. You can put parentheses around the table, but it isn't required. The sources are provided as a simple space-separated list of names; Lake already knows that the extension must be .c.

This build works as desired; if any of the two C files change then they will be recompiled, and the program linked. Lake knows that hello.exe depends on hello.o and utils.o, and it knows that these in turn depend on the corresponding source files. But it even knows that compiling the source files depends on the shared header - so that editing common.h (or just updating its timestamp with touch) will cause both of them to be rebuilt. Both of these compilers can be told to show what include files they depend on, using the -MMD and /showIncludes flags respectively. Lake uses this output to add extra dependencies to the compile rule for the files. Managing the dependencies manually is irritating, and easy to get wrong.

Say utils.c had a reference to sqrt. The lakefile should now be:

 c.program{'hello', src = 'hello utils', needs = 'math'}

Now for Unix builds, the math library will be linked in with -lm; on Windows, this is unncessary since the runtime already includes the math library.

Everyone has Needs

Lake uses this idea of needs for builds to specify their requirements on a higher level.

pkg-config is a marvelous utilty that provides exactly what is required here. Unfortunately, it is not used widely (or consistently) enough to be a one-stop shop for providing the gory details about every library. But Lake will try to use pkg-config if it is available to match needs. So a simple GTK+ C program can be built like so:

 c.program{'button',needs = 'gtk+-2.0'}

Lake resolves needs like this: first, whether it is built-in (like 'socket' or 'lua'), second, whether there are pkg-config aliases like 'gtk' available, and third, whether suitable global variables have been defined. So in resolving the unknown need 'foo' Lake will see if the globals FOO_INCLUDE_DIR, FOO_LIB_DIR and FOO_LIBS have been defined and point to existing directories. (Thereafter, it will try pkg-config.)

A lakefile is ultimately just a Lua script, and can have code that sets these variables explicitly.

 FOO_LIBS = 'foo3'
 if WINDOWS then
     FOO_DIR = 'c:\\foolib'
 else
     FOO_INCLUDE_DIR = '/usr/include/foo3'
 end

Explicit Rules: running Tests

Say I have a little Lua C extension. That's straightforward because Lake knows about Lua:

 mylib = c.shared{'mylib',needs = 'lua'}

Now I wish to run some Lua test files against the generated mylib.so or mylib.dll. For this, we make an explicit rule that connects Lua source files with an output file like so:

 lt = rule('.lua','.output','lua $(INPUT) > $(TARGET)')
 // populate the rule with targets; it depends on mylib
 lt ('test/*',mylib)
 // the default target depends on both the library and the test targets
 default{mylib,lt}

One important take-home here is that Lake works with targets in a very similar way to Make; the first target defined in a lakefile becomes the default, but if there are multiple targets then we have to define a dummy target that depends on these targets.

Now, maybe there is also a requirement that tests can always be run directly using lake tests. So we have to create a target dependent on the test targets, which first resets the tests by deleting the fake targets:

 target.tests {
   action(utils.remove, '*.output'),
   lt
 }

Depending on an unconditional action does the job. (However, this is not entirely satisfactory, since in an ideal world the order of dependencies being resolved should not matter, but this will do for now.)

Making the World a Better Place, one Semicolon at a Time

I remember an entertaining article by the famous Verity Stob on what to do when encountering C++ errors. One of the options was to write a Perl script to unmangle the errors so that they could be read by humans. She was writing satire, but like most good humour it was more than just a joke.

For instance, here is a wrong C++ program. Not terribly wrong, in fact almost competent:

 // errors.cpp
 #include <iostream>
 #include <string>
 #include <list>
 using namespace std;
 int main()
 {
   list<string> ls;
   ls.append("hello");
   cout << "that's all!" << endl;
   return 0;
 }

The response is pretty scary:

 errors.cpp:9: error: 'class std::list<std::basic_string<char,
 std::char_traits<char>, std::allocator<char> >,
 std::allocator<std::basic_string<char, std::char_traits<char>,
 std::allocator<char> > > >' has no member named
 'append'

Seasoned C++ programmers learn to filter their error messages mentally, but this is the kind of initial experience that drives kids to sniffing glue.

lake provides the ability to filter the output of a compiler, and reduce irrelevant noise. Here is the lakefile:

 if CC ~= 'g++' then quit 'this filter is g++ specific' end
 lake.output_filter(cpp,function(line)
   return line:gsub('std::',''):
     gsub('basic_string%b<>','string'):
     gsub(',%s+allocator%b<>',''):
     gsub('class ',''):gsub('struct ','')
 end)
 cpp.program {'errors'}

And now the error is reduced to:

 errors.cpp:9: error: 'list<string >' has no member named 'append'

And another case of rampant template trickery gone bad has been tamed, and our hypothetical beginner gets to Nirvana quicker.

This was, incidently, an accidental feature. I needed to parse the output of cl.exe to get the header dependency information (it is not written to a .d file like with gcc) so a postprocessing hook was needed.

What Next?

Naturally, this is not a new idea in the Lua universe. PrimeMover is similar in concept, and also has a bootstrap stage to construct a completely self-contained interpreter, which is definitely a strategy worth emulating.

I haven't dealt with topics like dependency-based programming because this is not intended as a manual (which is to be found here) This article is more about showing the advantages of a higher-level, needs-based build system based on a real programming language, which is compact enough that a fully self-contained Lake executable would be less than 300K.

A number of kind people have pointed out that 2,500 lines of code is a bit much for a single script, which is true, and of course I know better. Unfortunately I have too many projects and they keep me awake at night, demanding to be fed; the next evolution of Lake will have to take its turn.

A single file does make installing Lake easier; it just needs Lua and LuaFileSystem (known as the lua5.1 and liblua5.1-filesystem0 packages in the Debian/Ubuntu world) and for the script to be made executable and put on the path. If you have installed LuaRocks (also available on Debian/Ubuntu) then installing Lake is as simple as sudo luarocks install lake.

The priority is a sound system that is flexible enough to meet working programmer's needs, to get the right balance between declarative/dependency-driven and imperative. It is already possible to provide new needs for Lake by defining Lua modules that look like 'lake.needs.NAME', which can then be easily installed by LuaRocks or some more ad-hoc delivery system.

Using all the processing cores that developers have available is also a priority, which requires some interesting work in a language that does not do the necessary concurrency out of the box. The best cross-platform candidate would be Lua Lanes which provides a non-shared concurrency model with explicit data messaging using 'Lindas'.

Wednesday, 21 December 2011

Documenting Lua

Why is Documentation so Lacking?

As Barbie the Software Engineer might say: Documentation is Hard. It's not intrinsically fun like coding, and often gets written badly as an afterthought. In open source projects, where fun is so often the guiding principle, it can get badly neglected.

There are basically two kinds of comment; one that is aimed at other developers of the code and the other which is aimed at the users of a library. The latter is particularly hard and important, since we are building abstractions for other people to use, and if they have to actually read the code to work out how to use the library, that abstraction has broken. This is a common problem with language bindings to existing libraries; they will be announced as a 'thin wrapper around libfoo' and it's assumed that you can work out how to use the bindings from the libfoo documentation or from libfoo examples in C. Well, not everyone can (or needs) to read C well enough to make that practical. We know the classic rebuke, "RTFM!" but that assumes that there is a manual - it's often "RTFS!" these days.

Testing has become a minor religion in the last ten years, and mostly it's a good thing, especially when using dynamic languages. Tests are supposed to be the best kind of documentation, because they can automatically be shown to be correct. But if the scope of the tests is too narrow, then they can be harder to read than the source. That is, also write examples that can serve as tests.

We cannot ascribe poor documentation to laziness, since these projects are otherwise well-constructed and may have exhaustive tests. The developers clearly don't think documentation correlates with wide use by the community; perhaps communication is not a priority. After all, research mathematicians write papers and do not immediately think how to explain it to undergraduates; they are writing for peers.

This might seem an indirect criticism, but it isn't intended as such. (I resisted the urge to point to some representative Github projects for this reason.) The Open Source universe needs all kinds, from researchers to popularizers. In the 'social coding' universe, fork has become a verb of respect, so documenting an existing project and doing a pull request is a polite way to contribute to the usefulness of a project.

You might think that elaborate conventions and markup could get in the way of documentation. The Go standards simply require you to preface the package and any exported items with a plain comment; just about the only convention is that indented lines are shown preformated. And still those plain comments are often not written. Part of the problem is a variant on the "increment i by one" kind of comment, which is just an awkward paraphrase of the code. So a Stack.Push method might end up with the blindingly obvious "Push an element onto the stack". Anybody with any self-insight is going to find that silly, and so they don't do it. I have noticed that coding libraries and documenting their interfaces are modal activities; it's useful to approach documentation with a fresh head (much as how writing and proof-reading are separate but essential steps in preparing an article.)

The key thing is to care enough to return to the code with "beginner's mind", and finish the job.

The xDoc Tradition of API Documentation

APIs are rarely as self-documenting as their creators might think. Javadoc is probably the grand-daddy of a per-function style of API documentation, and it has inspired numerous xDoc tools for other languages. Here is an example of LuaDoc markup:

 --- foostr stringifies a list of Foo objects.
 -- @param foolist a list of <i>Foo</i> objects
 -- @param delimiter string, as in table.concat
 -- @return a string
 -- @see Foo, table.concat
 function foostr(foolist,delimiter)

Limited code inference occurs, so that we do not have to specify the function name, but otherwise everything is explicit. Dynamic languages pose a particular challenge here because we're forced to specify the parameter types in an informal way. Projects may define their own conventions, but there's no standard way to write 'list of Foo'. You may use see-references to other documented entities but they have to be in a @see section.

People have recognized for a while the limitations of this way of documenting APIs, which focuses on the individual pieces and can be silent on how to put them together, but it's much better than nothing. So the debate is often about making these comments easier to write. For instance, in a comparison between Doxygen and JavaDoc, Gushie says:

The most important problem with the Javadoc comment in the comparison is how much I need to concentrate on formatting issues while writing it. When writing Javadoc I am constantly thinking about what should and shouldn't be linked, whether the list will look right, etc. This is frustrating because, while I do want to document my code well I also want to focus on coding.

And that's it: a tool that forces you out of code flow is not going to make you happy about documentation.

One of the problems I have with LuaDoc is that HTML is awkward to type and ugly to look at, especially when you want to provide something as simple as a list. So one of the main requirements was that Markdown could be used instead. I try to be a good boy and not reinvent too many wheels, but LuaDoc proved fairly resistant to this change, since it helpfully stripped out the blank lines and line feeds from the comments at an early stage. But the tipping point was when I moved the Penlight codebase away from using the module function; LuaDoc loves the module function and it's often necessary to put it in a comment so that it will recognize something as a module. So ultimately the issue was that LuaDoc wanted code to be written in a particular way; futhermore, we all know that 'Lua does not have classes' but it's straightforward to work in an OOP style; again, there was no provision for such an choice. The guiding principle should be: a documentation tool should not limit a developer's choices.

So, wheel-reinvention happened, leading to LDoc. In a few days, I had something that did the job equally well, for myself. Seasoned campaigners will know of course that this is the easy bit; the hard bit is getting a tool that will work on other people's codebases. Thanks to some painstaking testing by Lorenzo Donatti and others, LDoc is now at the point where it's ready for prime time testing.

The lack of inline entity references in LuaDoc means that your references have to be footnotes to your comments. This style felt better:

 --- foostr stringifies a list of Foo objects.
 -- @param foolist a list of @{Foo} objects
 -- @param delimiter string, as in @{table.concat}
 -- @return a string
 function foostr(foolist,delimiter)

Using Markdown helps formatting lists:

 --------------
 -- creates a new @{Boo} object.
 -- @param spec a table of:
 --
 --  - `age` initial age of object (optional, defaults to 0)
 --  - `name` descriptive name used in caption
 --  - `foolist` list of @{Foo}
 --
 -- @return @{Boo}
 function Boo:create(spec)

(The blank lines are somewhat irritating, but I chose eventually to work with standard Markdown here; it is certainly less awful than the equivalent HTML.)

This kind of 'ad-hoc' table structure is a common pattern in Lua, and I've argued before that it's a good idea to have named types so that documentation can refer to them. An in-between option is to create a dummy type which just exists for documentation purposes.

Plain and Simple

Not everyone likes this 'tag soup' style of documention. For instance, this is the style followed in the Lua manual:

 ---
 -- Receives zero or more integers. Returns a string with length equal to
 -- the number of arguments, in which each character has the internal numerical
 -- code equal to its corresponding argument.
 -- Note that numerical codes are not necessarily portable across platforms.
 function string.char(...) end

This can be very effective with documenters who have a good clear prose style.

LDoc can support this by making the usual 'Summary' and 'Parameters/Returns' sections in the HTML template optional.

It was always awkward to configure LuaDoc, so I felt that LDoc needed a configuration file. As is often the case, Lua itself is an excellent format for such files.

 -- config.ld for Lua libraries
 project = 'Lua'
 description = 'Lua Standard Libraries'
 full_description = [[
 These are the built-in libraries of Lua 5.1
 Plus documentation for lpeg and luafilesystem.
 ]]
 file = {'builtin',exclude = {'builtin/globals.lua'}}
 format = 'discount' -- use lua-discount for formatting
 -- switch off the top summary and 'Parameters/Returns' in the template
 no_summary = true
 no_return_or_parms = true

(You can in fact even define your own template and/or stylesheet and reference them in the config.ld file.)

And here is the result, thanks to the API files from mitchell's TextAdept editor project.

The principle followed here is: allow the documenter as much control as possible, but make it straightforward for end-users to build the documentation. So a simple invocation of 'ldoc .' in the right directory will find the configuration file and do the rest.

Type Annotations

On the other end of the scale, it's useful to have type annotations for Lua functions. This is a requirement for full IDE support in the Eclipse Koneki project. Fabien Fleutot provided support for tag modifiers, so that one could say things like @param[type=string] name. I have provided convenient alias tags so one can say:

 --------------
 -- list available servers providing a service
 -- @tparam string service name
 -- @treturn {Server,...} list of servers
 function list_available(service)
 ...
 end

Beyond the built-in Lua types ('string','number',etc) there is no agreed-upon way to specify types, so some invention is necessary. The convention is that {T,...} is a list-like table containing T objects; (see the documentation for further discussion.) LDoc will attempt to do lookup on all identifiers within such a type specification, so that Server becomes a link to that type's definition.

Examples, Readmes and Command-Line Help

Per-function API documentation is often not enough. In particular, good examples can clarify the intended use, and narrative documentation can introduce the concepts and fill in the background. Complementary 'modalities' of explanation and extra redundancy allow end-users of different backgrounds and thinking styles to have various ways of understanding the topic.

So LDoc allows integrating the API documentation with examples and Markdown text as linked documentation. The best example I currently have is the winapi documentation. This is actually a C Lua extension, which is another LDoc feature. Here is the config.ld:

 file = "winapi.l.c"
 output = "api"
 title = "Winapi documentation"
 project = "winapi"
 readme = "readme.md"
 examples = {'examples', exclude = {'examples/slow.lua'}}
 description = [[
 A minimal but useful binding to the Windows API.
 ]]
 format = 'markdown'

Those of us who live in the command-line like to look up documentation quickly without messing around with a browser. Generating man-pages is an interesting and very do-able goal for LDoc, but man is showing its age and is pretty Unix-centric. Some great discussions with Norman Clarke inspired an LDoc feature where it looks up libraries on the module path and parses doc information.

So if you have an installed library with documentation, then it's easy to look up a particular function:

 $ ldoc -m pl.pretty.dump
 function        dump(t, ...)
 Dump a Lua table out to a file or stdout.
 t        {table} The table to write to a file or stdout.
 ...      {string} (optional) File name to write to. Defaults to writing
                 to stdout.

Thanks to mitchell's work at luadoc-ifying the Lua manual, this works for the standard Lua libraries (plus lfs and lpeg) as well:

 $ ldoc -m lfs.currentdir
 function        currentdir()
 Returns a string with the current working directory or nil plus an error
  string.

(ldoc -m lfs would list all the available functions.)

Further Work

It's possible to process the inner representation generated by LDoc using a custom Lua module, allowing multi-purpose pipelines. We're still working on use cases for this, but the basic machinery is there.

Other output formats could be supported; the program is meant to be extendable and I think generating LaTeX could be an excellent way of getting good-quality output.

Lua is surprisingly flexible at expressing concepts like modules and classes, so simple lexical code inference is probably not going to scale. Eventually we will have to use full static code analysis like David Manura's LuaInspect.

Thursday, 15 December 2011

MoonScript: A Lua-Based Language

Let a Thousand Flowers Bloom

There are literally hundreds of programming languages, most of which are historical curiosities, research tools or personal projects. You would think that most of the important innovations have happened, and existing mature tools available for all tastes. That is true, to a point: but we are still exploring the space of expressive notation for solving our programming problems. Here the practical programmer and the academic researcher diverge, of course; the latter sees most new languages as rehashes of things first done in the golden age of PL development.

The last few years has been a surprisingly fertile time for new programming languages. They range from Go (native code + new runtime), Scala (bytecode + JVM) to languages like CoffeeScript or Dart which translate to JavaScript. The trend is mostly towards static typing but with type inference helping to keep the syntax clear and uncluttered, with functional influences. There is some TIOBE and anecdotal evidence that the dynamic language usage has peaked, possibly because of the maintenance difficulties of large codebases (an explicit motivation for Dart's development, which has optional typing.)

MoonScript is inspired by CoffeeScript, but generates Lua code instead. JavaScript and Lua share many similarities like first-class functions, the m["name"] == m.name equivalence, and no conventional OOP constructs. People like the convenience and familiarity of class, however, so CoffeeScript, Dart and MoonScript provide explicit support.

Trying it Out

When reviewing a new language, it's useful to remember that programming languages take time and exposure to become mature. MoonScript is now on its second release, three months after the first, and getting out of its proof-of-concept phase. 'Leaf' Cocoran is doing all the right things; he has provided syntax files for some common editors, a binary for the notoriously compiler-shy Windows community, and has a good looking website with comprehensive documentation. And he is building on a very solid base, the battle-tested Lua 5.1 release.

Also, reviews are not tutorials; I won't try to cover all the syntax, but will try to give the flavour of the language.

MoonScript could generate Lua bytecode directly, but would hit the basic issue that the "Lua VM" does not have standardized bytecode. In particular, this would exclude MoonScript from using the excellent LuaJIT implementation, which is a known problem with the otherwise powerful Metalua dialect. And having a readable high-level language as the compilation output makes it easier to develop and trouble-shoot.

Although not compiler-shy, I am lazy and just downloaded the Windows binary (it's hard to resist a language delivered as a 212KB zip file. Besides, the 'non-POSIX' world doesn't get enough attention these days.) If you want to avoid the 'moon script.moon' incantation, then it's straightforward to tell Windows how to handle MoonScripts:

 ftype moonscript=d:\utils\bin\moon.exe %1 %*
 assoc .moon=moonscript

(These make global permanent changes, so you need to run as Administrator). Then add .moon to the system PATHEXT variable. The incantation is now just 'script'.

 -- script.moon
 print "Hi Ma", "No Parentheses!"

Wish-list Driven Design

In many ways, MoonScript is like a collection of features from a Lua user's wishlist; list comprehensions, shorthand for lambdas, switch statements, explicit classes, statements-as-expressions, switch statement, local-as-default. But Lua is the C of the dynamic languages; it has a small, very powerful core and 'conventional' syntax which has made it popular as an extension language. It moves slowly and carefully, and does not pander to 'Python envy'. MoonScript, on the other hand, will appeal to people with Python exposure, since indentation is used in the same way to delimit blocks.

I would not recommend MoonScript to a beginner in the same way I could for Lua itself, since it has a very concise syntax that appeals more to seasoned professionals. There is a lot more to remember, and always a number of ways to do similar things. This example shows the conciseness of expression:

 sqr = (x) -> x*x
 print sqr 4, sqr 5

The last statement in a function becomes its value; there's still return available but usually it's only needed explicitly when leaving a function before its end. print is still the same function it is in Lua, but parentheses are usually optional.

Well, cool: we've saved a lot of typing. That translates to something like this:

 local sqr
 sqr = function(x) return x*x end
 print (sqr(4),sqr(5))

Now saving on typing is an ambiguous virtue; if we wanted the ultimate compression, we would all be using APL and playing Code Golf. Classic Lua programmers prefer keywords to sigils, and fear that their language would end up like Perl. They say that reading code is a much more common operation than writing it. And that is fine and dandy (I mostly agree), which is why we need projects like MoonScript and Metalua to get a feeling for new notation.

Personally I like how MoonScript makes the functional aspects of Lua stand out more clearly. Higher-order functions are less cluttered with keywords:

 compose = (f,g) ->
   (...) -> f g ...
 printf = compose print, string.format
 printf "the answer is %d, '%s'", 42, "Everything"

List comprehensions are another favourite functional idiom:

 range = [i for i = 1,10,0.1]
 squares = [sqr(x) for x in *range]

Note the * syntax, which satisfies the common need to iterate directly over the elements of an array. (You can still say for _,x in ipairs range) These constructs result in inlined Lua code, which is a good decision given the very fast translation times for Lua and its modest resource needs.

Multiple for clauses are allowed:

 points = [{x,y} for x in *x_coords for y in *y_coords]

That generates about 17 lines of Lua output; hand-written would be about 10, which would still slow readers down and make them have to guess the programmer's intention.

Statements can be used as expressions, which is useful in functions:

 choose = (c,a,b) -> if c then a else b

In fact, there's a clever feature that for statements return tables:

 show = (t) ->
     for k,v in pairs t
         print k, v
 res = for i = 1,10 do 2*i
 show res

This is sufficiently clever to cause unintended consequences, so the rule is that this does not happen in function expressions and cause needless table generation:

 loop = -> for i = 1,10 do i
 print loop()
 -->
 (nada)

It's probably too clever to be truly wise, given that list comprehensions do the job more explicitly. However, it can be used to go beyond the list comprehension syntax:

 values = {1,4,3,5,2}
 v = for v in *values do switch v
     when 1 then 'bad'
     when 4 then 'cool'
     when 5 then 'excellent'
     else "uh-huh"
 -- v is now {'bad','cool','uh-huh','excellent','uh-huh'}
 --

New with this release are table comprehensions, which are a generalization to map-like tables. These use curly braces to distinguish themselves, and the expression must be double-valued, with the first value becoming the new key and the second the associated value. So this expression turns an array into a set, that is t["hello"] is true if ls contains the value "hello".

 t = {k,true for k in *ls}

At this point, it's good to remember that we are still in Lua land, and there is no automatic pretty-printing of tables - which is wise because tables are the ultimate flexible data structure. (You can choose the string representation of your own types easily enough.) There is a small library included which provides a generic table dumper:

 require 'moon'
 moon.p {
     one: 'hello',
     10,
     20
 }
 -->
 {
     [1] = 10
     [2] = 20
     [one] = "hello"
 }

(For those used to Lua, note the use of : for key-value assignments in table constructors; the key may also be a keyword. For those who are not, note that tables can both be 'arrays' and 'hashes' - they are general associative arrays which are particularly efficient at regular array indexing. Like electrons, they are both waves and particles.)

However, despite the perception, there are batteries for Lua and MoonScript can consume them happily.

Using Existing Lua Libraries

MoonScript already includes LuaFileSystem and LPeg as standard libraries.

 total = 0
 for f in lfs.dir "." if string.match f "%.lua$"
   size = lfs.attributes(f).size
   print f, size
   total += size
 print 'total',total

(It also comes with lua-getopt for argument parsing, but that's an awkward, no-documentation kind of library.)

My favourite command-line parser is Lapp, which is part of the Penlight suite of libraries, since it parses the actual flag names and types from the usage string:

 -- mhead.moon
 require 'pl'
 args = lapp [[
     A simple head utility
     -n,--lines (default 10) number of lines to print
     <file> (default stdin) file to print; can be stdin
 ]]
 for i = 1,args.n
     line = args.file\read!
     if not line then break
     print line

On Windows, the directory for Lua packages is relative to the executable. So if I install moon.exe to d:\utils\bin, then Lua packages must go in d:\utils\bin\lua. To install Penlight simply involves copying its pl directory to this lua directory. For other systems, MoonScript shares the usual global Lua module path.

To read configuration files (both Unix and INI-style) we can use pl.config

 require 'pl'
 test = [[
 # test.config
 # Read timeout in seconds
 read.timeout=10
 # Write timeout in seconds
 write.timeout=5
 #acceptable ports
 ports = 1002,1003,1004
 ]]
 t = config.read stringio.open test
 pretty.dump t
 [[ --output--
  {
     ports = {
       1002,
       1003,
       1004
     },
     write_timeout = 5,
     read_timeout = 10
   }
 ]]

Classes

By the time people get to Lua (or Go) they have been sufficiently indoctrinated to instantly miss classes. Lua prefers to define more general metaprogramming techniques, which allows a competent user to roll any kind of custom OOP framework. (Unfortunately, too many people do this, so interoperability becomes a problem.) But ultimately all that matters is that the duck quacks. Lua does require you to indicate that the quacking applies to a particular duck, or to all ducks, much as a C++ programmer uses -> and ::.

In Lua, a method call is:

 duck:quack()

And in Moonscript:

 duck\quack()

(Idiomatic MoonScript would actually be duck\quack! but let's change one variable at a time.)

I'm not 100% crazy about the backslash here, but : has now got a more conventional job defining value/key pairs in MoonScript (and there was no other punctionation available ;))

So here is a MoonScript class, bit by bit:

 import insert,concat,remove from table

the import statement is one of those nice-to-haves which would be very useful in Lua, since the equivalent is the noisy and redundant:

 local insert,concat,remove = table.insert, table.concat, table.remove

A class is an intented block containing methods

 class List
     new: (t) =>
         @ls = t or {}

Note the colon, instead of =; this reminds us that we are putting these functions into a table. The fat arrow => means that the function has an implicit self argument; here it's equivalent to (self,t) ->.

@ls is just sugar for self.ls, as in Ruby. (The new method will be indirectly called as a constructor).

Our chosen representation for a list is a table field ls. This can be manipulated by the usual Lua table functions, which we previously imported:

 add: (item) =>
     insert @ls,item
 insert: (idx,item) =>
     insert @ls,idx,item
 remove: (idx) => remove @ls,idx
 len: => #@ls
 __tostring: => '['..(concat @ls,',')..']'

table.insert is basically two functions wrapped up as one - it both appends and inserts. #@ls is one of those collisions of punctuation that one just has to get used to in any language - it helps to read it as #self.ls (and you can use self explicitly if you like.)

Any Lua metamethod can be specified in a class. A MoonScript class is the metatable for all its instance objects, with __index pointing back at the metatable so the object can find its methods. This is the most common way of implementing 'classes' in Lua.

Unfortunately, # cannot be overloaded in Lua 5.1 for tables; __len only applies to userdata defined by C extensions. (This is one of the welcome Lua 5.2 improvements)

 find: (item) =>
     for i = 1,#@ls
         if @ls[i] == item then return i
 remove_value: (item) =>
     idx = self\find item
     self\remove idx if idx
 remove_values: (items) =>
     for item in *items do self\remove_value item

if statements come in two flavours: multiline, where the following block is indented, and single statements that use then. The same applies to for, where the single statement version has an explicit do.

Any statement/expression can also have an if clause, called a 'line decorator'.

Now list comprehensions get their turn:

 index_by: (indexes) =>
     List [@ls[idx] for idx in *indexes]
 copy: => List [v for v in *@ls]

And finally we define extension, iteration and concatenation:

 extend: (list) =>
     other = if list.__class == List then list.ls else list
     for v in *other do self\add v
     self
 __concat: (l1,l2) -> l1\copy!\extend l2
 iter: =>
     i,t,n = 0,@ls,#@ls
     ->
         i += 1
         if i <= n then t[i]

Any instance of a MoonScript class will have a __class field; I make this check because it's useful to allow a list to be extended by a plain vanilla table.

The iter method needs some explanation: in Lua, the for in statement expects a function that it can repeatedly call to get each successive value of the sequence, until that function returns nil. This method returns a closure with upvalues i, t and n.

And, exercising List:

 ls = List!
 ls\add 10
 ls\add 20
 ls\remove_value 10
 ls\remove_value 15
 ls\add 30
 ls\remove 1
 for v in *{1,2,3} do ls\add v
 print ls, ls\len!
 print ls\index_by {2,3}
 for v in ls\iter!
     print v
 print (List{'a','b'})..(List{'A','B'})

No type is complete without a definition of equality. == in MoonScript, as in Lua, compares simple values, not referencews. Objects are equal if they are the same object; (string equality works as expected because all Lua strings are guaranteed to be internally unique.) Generally, this is a good idea (none of JavaScript's 'helpfullness' here!). The relavant metamethod is __eq:

 __eq: (l1,l2) ->
     return false if l1\len! != l2\len!
     l1, l2 = l1.ls, l2.ls
     for i = 1,#l1
         return false if l1[i] != l2[i]
     return true

As another example of a Lua wish-item, note that ls\add without arguments is a valid expression, called a 'function stub',

 ls = List {1,2}
 add = ls\add
 add 3
 add 4
 assert ls == List {1,2,3,4}

ls\add 3 is short for ls.add ls 3; ls\add is a partial function application that binds the self argument.

See here for the complete code listing.

use as a DSL

One of the things I look for in new languages is how amenable their syntax is to the creation of embedded domain-specific languages.

The MoonScript author has a static website generator called sitegen where you specify your configuration with a site.moon file:

 require "sitegen"
 site = sitegen.create_site =>
   deploy_to "leaf@leafo.net", "www/sitegen"
 @title = "Sitegen"
 @url = "http://leafo.net/sitegen/"
 add "index.html"
 add "doc/ref.md"
 site\write!

We've met the fat arrow (=>) before in methods, but it can be used anywhere. Here => is shorthand for (self) ->. Now the @title shortcut makes sense, since it's just self.title.

The Lua equivalent is certainly more verbose, although I'm not sure we're losing much on readability:

 require "sitegen"
 local site = sitegen.create_site(function(self)
    deploy_to("leaf@leafo.net","www/sitegen")
 self.title = "sitegen"
 self.url = "http://leafo.net/sitegen/"
 add "index.html"
 add "doc/ref.md"
end)
 site:write()

sitegen is the best existing example of real working MoonScript. As the author says modestly, "apart from the compiler". (That's right, MoonScript is now self-hosting.)

Problems and Irritations

You'll notice the necessary parentheses when concatenating two List expressions. Although we are encouraged to leave them out unless they are necessary, the rules are not as straightforward as they could be. For instance, this equivalence contradicts the above rule; note how whitespace matters:

 L"frodo" + L"bilbo" == L("frodo") == L("bilbo")
 L "frodo" + L "bilbo" = L("frodo" + L("bilbo"))

This comes from a Lua convention that parens are not needed if the function has a single string argument, but results in a special case that is likely to bite more than one person. It's easy enough to learn to read indentation as syntax, but making a single space syntactically significant is going too far. I would see this as destructive interference from the base language.

There are other inconsistencies, like you cannot say @\f to call another method when inside a method body. (This would lead to serious punctuation clusters like @\f! so perhaps this is a feature ;))

Generally, the compiler is not so very helpful and gives non-specific parse errors, and the line it does complain about is often not the problem line anyway. So I found myself having to read the manual carefully to work out issues. It reminded me of my Seventies experience with mainframe Fortran, where the result of painstaking work at the card puncher would lead to the equivalent of 'Que?'. And run-time errors would usually end up as a six-digit error code which you would then have to look up in the IBM manuals, which were bolted down like Medieval manuscripts. We've come a long way, and it shows how important good diagnostics are to learning a system: the compiler as tutor.

But hey, it's a young language, these are all fixable faults. It's a must-play for anybody interested in the future evolution of Lua, and could find an audience among CoffeeScript enthusiasts who might appreciate a lighter, faster runtime, especially with more generally useful batteries.

Thursday, 15 September 2011

Strict Tables in Lua

Spelling Mistakes are Runtime Errors

Undeclared variables in dynamic languages are a well-known pain point. The compiler has to make an assumption about the scope of any undeclared variable; in Python, such variables are assumed to be local, and in Lua they are assumed to be global. (This is not entirely correct because of function environments, but will do for a first pass.) Furthermore, Lua does not distinguish between 'undefined' and 'null'; the value of such variables will always be nil, which is of course a perfectly valid value for a variable.

The consequence is that misspelt variables will evaluate to nil; if you are lucky the code will crash nearby with an error, but the nil can be passed along until it's not clear who to blame. So serious Lua programmers are strict about detecting undefined globals.

There is a dynamic approach provided by etc/strict.lua, which is part of the standard Lua distribution. Globals are looked up in the global table _G, which is otherwise a normal Lua table. You can give it a metatable and a __index metamethod, which is only called if the variable was not already present in the table. By keeping a table of known declared globals, this can throw an error on any undeclared variable access. This is definitely a case where you need to fail hard and early as possible!

(Another approach is static analysis, for instance David Manura's LuaInspect which has the advantage of making mispellings into compile-time errors. It has experimental integration into the SciTE editor.)

The pattern I will describe brings stricter run-time checking to other Lua tables using the same principle. But first let's examine some practices that are common in Lua code. Named arguments to functions are not supported, but it's easy to use tables to get the same result:

 function named(t)
   local name = t.name or 'anonymous'
   local os = t.os or '<unknown>'
   local email = t.email or t.name..'@'..t.os
   ...
 end
 named {name = 'bill', os = 'windows'}

Although this is not the most efficient way to pass arguments to a function, it serves the purpose well, particularly with Lua's function-call syntax sugar that lets us leave out the parentheses in this case.

This idiomatic use of anonymous structures is common in Lua code. Need to keep a few things together in one place? Make a table! The pattern also appears in JavaScript which has the same identity between t['key'] and t.key in dictionaries. And LuaJIT can optimize field accesses in inner loops to C-like speeds.

Such ad-hoc tables are always open to extension, so people add extra fields as the need occurs. At this point strong-typing people are starting to hyperventilate: how can such code be ever reasoned about correctly? The answer is, fine - up to a certain point of program complexity. Thereafter you need to get disciplined.

Lua is not inherently a weakly-typed language, but there is a tendency to use it like so. One problem is how to document this pattern, for instance, how to document the function named above? If functions take specific named types for their arguments, then we can refer to the definition of those types in their documentation. Identity is also very useful for debugging and dynamic type-checking.

Give a Dog a Name ....

I'll show how the idea of 'strict tables' helps this structuring problem and also how to catch another class of misspellings accurately. First, a strict strict has a known set of fields with default values (which also establish the type of the fields):

 Strict.Alice {
     x = 1;
     y = 2;
     name = '';
 }

This statement causes a constructor Alice to be introduced into the current environment:

 a = Alice {x = 10, y = 20, name = "alice"}

Any of these fields may be absent in the constructor call, and in particular Alice() will give you a new Alice-struct with the initial default values. However, setting an unknown field or setting a known field to the wrong type is a run-time error:

 b = Alice {x = 10, Y = 20, name = "bob"} -- > error: field 'Y' is not in Alice
 c = Alice {x = 10, y = 20, name = 44} -- > error: field 'name' must be of type string

What does 'wrong type' mean? Here the convention is that we compare the type names, but if the types are tables or userdata we compare their metatables.

Trying to access an unknown field of an Alice-object will likewise result in an error:

 print(a.Y) -- > error: field 'Y' is not in Alice
 a.Y = 2  -- > error: field 'Y' is not in Alice

The second failed assignment shows that Alice-objects are closed, which is a further restriction. (In the case of the original strict.lua, the global table is always open to new variables.) A little less freedom often relieves us of later anxiety, and here allows for checking field spelling mistakes immediately when they happen.

We basically incur no extra run-time overhead for this checking. This is because __index (and its cousin '__newindex`) only fires if lookup fails. (In Lua 4, such functions were called fallbacks, which remains a fine bit of descriptive terminology.)

By default, these objects know how to convert themselves to strings sensibly:

 print(a) --> Alice {y=20,x=10,name=alice}

They directly solve the documentation problem by being themselves documentable:

 -------
 -- Check alices.
 -- @param anAlice an @{Alice} object
 -- @see Alice
 function check_alice(anAlice)
 ...
 end
 -----
 -- Alice.
 -- @field x
 -- @field y
 -- @field name
 -- @table Alice

The benefits of named, unique types are well known:

  • error messages are explicit (we know what kind of dog caused the problem.)
  • debugging is easier, since these dogs know their name and their kind
  • type identity makes type checking possible (Is this dog an Alsatian?)

This will be self-evident to any Java (or Python) programmer; why isn't this pattern more widely used in Lua? First, anonymous types are very good at creating recursive structures akin to S-expressions - which will be self-evident to any Lisp programmer. Second, the idea of extended type is not built-in to the language, resulting in multiple ways of declaring dogs and interoperability issues. And finally, because it can be so convenient to play fast and loose with your data. For instance, you want to deliver something to another part of the system and there's no 'official' way to do it. But you know that there's an object which will end up there later, so you attach some data to the object and make a special case at the receiver. It's a bit like the informal arrangements people make like 'when you're in Singapore can you pick up that new toy for me?' rather than using a courier. (I have enough disciplined instincts to know that this is not the way to produce software that's clear to others, but it's a convenient way to get what you need.)

Although not strictly necessary, it was hard to resist adding a few features. Consider this:

 Strict.Boo {
     name = 'unknown';
     age = 0;
     __tostring = function(self) -- can override __tostring
         return '#'..self.name
     end;
     __eq = true;   --- default member-equals comparison
     __lt = 'age';  --- use this field for less-than comparison
 }

The default string conversion may not be desired, so you may override it using the __tostring metamethod. Note in fact that the 'specification' table becomes the metatable for all named objects, so you can specify any of the available metamethods. (In Lua 5.2 you can even specify a finalizer using __gc.)

As a convenience, setting __eq to true means that you want a plain naive field-by-field comparison (otherwise objects are all unique table values.) And __lt can be given the name of the field for < comparisons.

Defining the < operator means that you can directly sort lists of these objects:

 ls = {Boo{age=13,name='F13'},Boo{age=5,name='F5'},Boo{age=20,name='F20'}}
 table.sort(ls)
 for _,b in ipairs(ls) do print(b) end
 --- > output:
 #F5
 #F13
 #F20

A Question of Notation

The notation for defining new strict tables I've chosen needs some elaboration. Without any sugar, it would look like this:

 Strict("Person",{ name = '', age = 0 })

We get closer to the desired notation by currying (that is, expressing a function of several arguments as a chain of single-argument functions):

 function Strict(name)
     return function(spec)
       ...
     end
 end

Which would allow

 Strict "Person" {name = '', age = 0}

To get Strict.Person {...} is easy; Strict is a table which is given a __index metamethod; accessing any new name causes it to be called, and it will then return the actual function as above:

 Strict = setmetatable({},{
     __index = function(self,name)
         return function(spec)
         ...
         end
     end
 })

Further Elaborations

There are other approaches to the problem of checking the structure/type of Lua tables, of course: have a look at how LuaRocks does a sanity check on the rockspec format. This is akin to the idea of defining a 'schema' for XML, although a good deal more readable.

The implementation discussed here focuses on creating a closed, named type with declared fields and their types. It's currently just over a hundred lines, which is my self-imposed limit with these article demonstrations, but there's a number of cool features which could be added. Any library has a real implementation and an imaginary part, which is the space of possibilities; it would be boring to neglect the latter.

If we wanted to enforce type-checking on these fields (such as a.name = 42) then we need an extra indirection using the proxy-table pattern. That is, the Alice-object itself would not contain anything except a table containing its values; then __index will always fire and would look up the key in this value table, after performing some sanity checks. In that case, performance would be affected (although if such lookups did not happen in inner loops then the penalty may well be not measurable anyway.)

It could be useful to optionally allow for field ordering:

 Strict.OrderedPerson {
     "Represents a Person for our catalog";
     {name = ''; "full name of person"},
     {age = 0; "age in years"}
 }

which would allow the constructor syntax OrderedPerson("Dilbert",38). The doc-strings would not be obligatory but can be used (for instance) to automatically generate a basic entry dialog for the data.

It would be possible to also add methods to these strict tables but they are really meant to represent classic dumb data; for more conventional OOP in Lua there are many options (As the great Grace Hopper said, the wonderful thing about standards is that there's so many of them to choose from; my personal favorite which I use in Penlight is here).

An extended concept of 'type' is problematic precisely because there are so many object-oriented schemes possible. For instance, there are a number of imcompatible inheritance schemes that make asking the question 'is A a subtype of B?' particularly tricky.

But we could extend the type specifications used by strict tables in useful ways. Currently the type of a field is the type of its default; what if the type was a Lua string pattern? So '^%S+$' would mean 'a string with no spaces'. Or if {0} meant 'an array of numbers'?

 Strict.Data {
     name = '^%S+$';  --- or give the pattern a name, e.g. Strict.no_spaces
     factor = Strict.range(0,1);
     children = {Child()}
 }

(This would further enable our hypothetical data-to-dialog generator to give more specific validation of user input.)

The idea of 'documentability' can be taken further; if I had a function that received an object that had a read method, then the obvious equivalent to strict tables would be interfaces:

 Interface.Readable {
     read = true
 }

My function could then say Interface.check(1,rdr,Readable) to give a meaningful assertion on the first argument rdr. Even if I didn't use these assertions, simply making the argument more documentable could be a sufficient reason to have named interfaces. The contract can be specified and optionally enforced; it cannot be specified in such great detail as in statically-typed language, but it's still useful.

Finally, not everyone is as lax as I am about creating new globals. Strict returns the new type, but also creates it in the current environment. A more careful person would probably want to remove the line that creates this global. Maybe Stricter ?

This article was based on the original lua-users wiki entry; here is the code.