Why I like Lua? Here is an attempt at an answer:
1- Tables
Lua's answer to arrays, lists or any kind of data structure is Tables. The concept goes by many names, and depending on your background, you might know them as associative arrays, hash map or dictionary. In short they're data structures that map keys to values. The simplest case:
> a = {key1 = "first", key2 = "second" }
> print (a)
table: 0x94fcf10
> print (a["key1"])
first
> print (a["key2"])
second
>
Note that if you omit the keys, they get assigned numerical indexes by default(
starting with value 1):
> b = {"one", "two"}
> print(b[1])
one
>
The thing I like most about tables is the following piece of syntactic sugar. If the key is
a string value, then
t["key"] is equivalent to writing
t.key. As you can probably imagine, and as we will see later, the values can also have function values, as a result you can see that tables behave like a very simple implementation of the C++
struct keyword or even more, just like Python namespaces. In other words, every data structure in Lua is a table.
For instance, modules, which are nothing more than a namespace, also follow this rule:
> print(string.len("hello"))
5
> print(string["len"]("hello"))
5
Note that the current implementations of CPython use dictionaries for namespaces and in this sense behave a lot like Lua. However the documentation clearly states that this behavior is not part of the python spec, is implementation specific and as such, might be modified at any moment. Lua on the other hand puts its table forward, considering them a core feature of the language.
Another cool thing about Lua tables is that your keys can be anything (except
nil, the empty value). Here's an example of implementing a 'switch' call with a table, by using booleans as keys:
> abs = function(x)
>> test = {
>> [true]=-x,
>> [x>0]=x,
>> [x==0]=0}
>> return test[true]
>> end
> print (abs(-3))
3
For the record, the above construct is a bit awkward; for readability, you should prefer using nested if .. then .. elseif .. then .. else .. end. I only use it to demonstrate what tables are capable of.
2- Functions
Lua has lambdas. It creates anonymous functions by using the keyword
function. If this doesn't make sense to you, let me explain. You noticed in my 'abs' example above that function definition happen by assignement. There are no special definition keywords, although there is syntactic sugar to make things more 'intuitive'. The following to statements are equivalent:
foo = function (x)
function foo (x) -- this is the syntactic sugar
Functions can be assigned to a variable, which implies they can be given as arguments to functions, or as return value of other functions. Take a look at this piece of code:
function eat(food)
print ("I eat " .. food)
end
function drink(food)
print ("I drink " .. food)
end
function swallow (food)
func = {[true] = eat,
[food == "juice"] = drink}
func[true](food)
end
swallow("juice")
swallow("apples")
Output:
I drink juice
I eat apples
3- nil
In Lua, nil is a special variable type that is analogous to NULL (C/PHP/...), null (java, C#, ...) or to a certain extent None in Python. However it does present some appreciable aspects.
Lua is dynamically typed. This means any variable can contain any kind of value. Every variable has the value nil, until it's assigned its first value. As a result, assigning any variable to nil is equivalent to deleting it. (Do not think about memory management, it's a GC language). You can test if a variable exist by comparing it to nil:
> print (x == nil) -- at the beginning of the program, x does not exist
true
> x = 1
> print (x == nil)
false
nil has also the wonderful ability of testing to false.
> print (nil or true)
true
> print (nil or false)
false
We can use this property to define default args to our functions:
> function add_or_incr (a, b)
>> b = b or 1
>> return a + b
>> end
> print(add_or_incr(5, 2))
7
> print(add_or_incr(10))
11
As you can see, there's nothing really out-of-the-ordinary about Lua (but very few 'modern' languages can claim to be novel). It's a simple scripting language, and if you've ever seriously used one, you should feel right at home. I don't know much about concurrency, so I cannot say much about that.
About the common implementation, I haven't run any tests nor used it in production. I know that it provides a really strong embedding interface (which is what lead it to become the de facto script language for games). If you feel like trying the language before installing it, you can
do so in your web browser.
That's all :)