Spiria logo.

Learning LUA for Python Developers

May 2, 2016.
In a previous job, I programmed in Lua for 6 months to create a game for mobile phones. During the process, I noticed several similarities between Lua and Python.

In a previous job, I programmed in Lua for 6 months to create a game for mobile phones. During the process, I noticed several similarities between Lua and Python.

In order to write this blog, which aims to present Lua to Python users, I decided to get back into Lua programming by creating another game in the same environment I had worked in previously: Corona SDK.

While Lua does have pretty good documentation, it isn’t as easy to use as Python’s. The following are the highlights of the differences between the two languages, with a view to easing the transition from one to the other.

Tables

Python supports several different data structures: lists, tuples, sets and dictionaries.

In Lua, there is just one data structure: tables. While this one structure does it all, it is basically as much a list as a dictionary. The Lua module is a file, similar to Python. The difference is that in the end, the module must return a table. The table represents the module.

A table inside a file is like a class, to which you can add member data and functions.

-- this is a comment.

local gameScene = {} -- gameScene is a table.

gameScene.score = 0

function gameScene:loadScene() ...

-- before the end of the file, go back to table.

return gameScene

Tables are very flexible.

The method of declaring the function loadScene in the previous example is in fact syntactical sugar for:

gameScene["loadScene"] = function() ...

So we can in fact add functions to a table at any time. Further, for variables, the period “.” refers to an entry in a dictionary.

gameScene.score = 1000

is the same as:

gameScene["score"] = 1000

Which can lead to conflicts, if you’re not careful.

This example demonstrates Lua’s flexibility, while highlighting the importance of being organized. When functions and member data are poorly defined, they can eventually become a puzzle.

Lambda and Closures

Lambdas in Lua are not special, since you can add functions to a table as follows:

uneTable.testfct = function() ...

What is special, and less intuitive, is the principle of closures and their upvalues.

local x = 5

local uneTable = {}
uneTable.testfct = function(y)
   x = x + y
end

print x
uneTable.testfct(6)
print x

Output:

5
11

The x variable is an upvalue of the function testfct.

Missing Operators

Operator +=

Instead, you have to use the long version:

x = x + 5

Operator !=

Replace by ~= :

local scoreData = {}
if scoreData ~= nil and scoreData[“level_one”] ~= 0  then
   code
end

Unary operator !

Like in Python, we must use the keyword not.

Keyword Self

Self is used in Lua, but slightly differently. In Lua, the word self is implicit when using the colon to call a function, whereas in Python, the word self must be included in the list of parameters.

aTable.aFonction(5, 6)

Since aFunction is called on aTable with a period, self is “nil” within the function.

aTable:aFonction(5, 6)

Since aFunction is called on aTable with a colon, self is “non-nil” within the function and represents aTable.

There are advanced techniques to modify the behaviour of tables, but this goes beyond the scope of this introductory article.

Function and Logical Expression (Control Statements)

Contrary to Python, Lua doesn’t require specific indentation. Functions are written as follows:

function gameScene:enter()
  code
end

Same for logical expressions:

if x > 6 then
  code
else
  code
end

for elem : elemTable do
  code
end

Import Replaced by Require

Require is the word used to reference modules from other modules.

In the section on tables, I explained how modules had to return to their table at the end. Here is an example:

==== In the file gameScene.lua =====
local gameScene = {}

function gameScene:enter()
end

function gameScene:exit()
end

return gameScene

==== End of file gameScene.lua =====
==== In the file mainMenu.lua ====

local gameScene = require "gameScene"
gameScene:exit()

==== End ====

Take note:

  • Functions end in “end”;
  • require does not require the Lua file extension. All referenceable files carry that extension;
  • require does not require parentheses, just like import in Python.

Coercion

The system is implicit in Lua, while in Python, you must use the str function to go from an integer to a string (cf. Programming in Lua, ‘Strings’).

Useful Links

To learn more:

 

[Photo Technodwarf.]