Learning Lua as a Python Developer
This tutorial is not the millionth tutorial that walks you through basic concepts of Lua language. First there are quite excellent tutorials that actually aims to do exactly that. This post would be to tell a tutorial on Lua from a Pythonista, comparing Lua features with various Python features and try to create various associations. Make no mistake, I will actually go through basic concepts but somehow comparing the Lua with Python all the time. I think these two languages are very similar in various aspects and those associations may make the learning curve a little bit smoother.
(If you ask me the steeper the learning curve is better, as the slope is how fast you could learn(x axis is time). The steeper curve has higher slope, therefore you could learn faster. Not sure why steeper learning curve has connotation of hard concepts or hard to understand material. Contrarily, we should say steeper learning curve for easy concepts. But, hey. Nobody claimed that the languages are and should be consistent.)
Anyways, where was I? Yes, Lua it is. And of course Python. Making comparisons between languages not only makes you remember the syntax easily but also you could get a feeling of the language if the two languages are very similar in various aspects. If you learned Java as a your first language, then whenever you learn an OOP(Object Oriented Programming) focused programming language, you would get the same feeling. Classes and objects are kind of big deal. You’d better use it wherever you can.
But let’s step back for a second. Why Lua? It is compact, fast and dynamic. It is somehow easy to learn. You could also list a bunch of advantages of Lua as well, but my reason was quite pragmatist if there is a spectrum of reasons why you learn a new programming language. My aim is to learn more about tools in Deep Learning and more specifically Torch.
And Lua is all good, huh? Not really. It is not very popular so community support is not there and not good comparing to Python. The standard library is not very large. From Python’s batteries included approach, it gets hard to get used to DIY(Do It Yourself) from there should be a library for that if it does not exist in the standard library already.
Similarities
Strings
String definitions are same, ’
or ”
works and they do not have any difference. Python uses ”””
for multi-line strings and Lua uses [[]]
. Strings are immutable and can be concatenated to each other. Lua uses ..
as concatenation operator where Python uses good old plus operator +
. len
, split
and various functions in string module works as in the same way in Python.
Logical Operators
not
, and
, or
works in the same way as you expect. Only difference is nil
and false
are evaluated as false
in Lua where in Python empty string, list, set and even 0 are evaluated as False
.
Table usage
Table syntax and usage of sets and lists are very similar to Python.
table = {‘first_key’= 10, ‘second_key’= 20}
list = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’} -- They get automatically 1 upto 6 as keys
-- Under the hood it is still an associative array
print
and type
functions
They behave exactly the same way as in Python. You could get the type information via type
function and print out the results with print
function.
No braces and semicolons
There are no braces and semicolons. They made the compromise on the end keyword which is understandable. As long as developer adheres the indentation for his function definition and programming style, then it should be as readable as Python.
There is one way and prefereably only one way to do things
Since the language is compact and somehow barebone, there is generally only one way of doing things. Actually, sometimes there is not.(e.g. getting keys from a table) This makes it easy to read the code that other people wrote if they have not exploited the metatables quite a lot.
Explicit self
s
Both languages use explicit selfs in function definition. Lua even attempts to pass the object in a regular function call(so much object oriented after all). However, it provides a syntactic sugar which I will show in a bit.
Multiple Return values and multiple assignment
Both languages support returning multiple values in functions and you could assign multiple assignment as well. In Lua, it looks like this:
first_table, second_table = {}, {}
first_table.x = “first_value”
first_table, second_table = second_table, first_table
If there are more variables in the right hand side than the left hand side in the assignment operation, then Lua errors where Python raises ValueError
exception, though.
Both Languages support unpack
ing lists
If you have a function, you could put all of the parameters into a list and then unpack
them in Lua where in Python you would use *
prefix to the list to unpack.
In Lua, the following
is similar to
in Python.
Enumeration on table
s or dictionaries
Both languages provide a way to traverse lists with enumerated version. This holds true for dictionary or table as well.
In Lua, one could call pairs
in the table to traverse both key-value in the table. If you call ipairs
in the list, then you would get the enumerated indices along with the values that are in the list.
Iterators gonna iterate
for
can be used for iterators in both languages. One can also define custom iterators as well which could be used in the for construct as well, which is pretty nice.
Differences
Whitespace vs end
keyword
Lua opts in using end
keyword for ending function definition or for loop where Python uses whitespace for function definition, control flows and so on.
Functions
Function definitions are somehow similar to Javascript dropping {}
in favor of end
keyword.
could be also assigned to a variable similar to Javascript. You could define anoymous functions and assign them into a variable in Python to be fair. But more ofthen than not, people just pass the function itself rather than the variable that is assigned to.
Variable Scope
All of the variables are defaulted as global variables. Not sure why the language creators thought this is a good idea, but you could explicitly put local
keyword in front of the variable declaration to make it “local”. Contrarily, you could explicitly make a global variable putting global
in front of the variable declaration.
Tables vs Dictionaries, Lists and Sets
In Lua, we trust tables, Python needs to bring dictionaries, lists and sets. Tables are the only compound data structure(did anyone tell that Lua is a very compact language). Tables are associative arrays similar to dictionaries in Python, but they could be also used as lists(defaulting the keys as integers).
x,y
“range” syntax includes beginning and end-point
The tables when they are used as lists, start indexing at 1. When you define a range of integers using 1,100
, which produces 100 integers from 1 upto 100 including 1 and 100. If you have the list, you could get the length of the list via #list
.
Objects
Lua does not support object oriented programming. They provide certain ways of doing OOP, similar to Javascript’s prototype based style, but even that requires somehow different syntax to call the object. Of course, there is no object by the way. It is a table which you could call functions from it. You could add almost any behavior on tables via “metatables” though.
is nothing but a syntactic sugar for the following for example:
Lua is fast
I meant LuaJIT is fast. Comparing to Python, it is quite faster, which is important if you are doing expensive numerical operations. Considering its dynamic nature, this is a little surprise to me,but it is a good surprise.
Lua assigns nil
when a variable is not defined
If you are accessing a variable that you did not define in Lua, it does not error, it silently assigns a nil
to the variable and does not complain where you would get a NameError
in Python. In general, since most of the things are tables and if you access a non-existent key to the table, it simply returns nil
, there would be less explicit error or exception but rather nil checking for those statements if the key actually exists in the first place in the table.
Lua does proper tail recursion
Lua does proper tail recursion where Python does not.