Know JavaScript, and want to learn Lua? Here's are some quick facts about the similarities and differences. See Learning Lua for more resources.
Lua and JS are both case sensitive. true and false are boolean literal values, and completely different from True or TRUE.
In Lua, like JS, you may always pass more or fewer arguments to your function than your function declares:
function showem( a, b, c )
print( a, b, c )
end
showem( 'first' ) --> first nil nil
showem( 'first', 'second' ) --> first second nil
showem( 'first', 'second', 'third' ) --> first second third
showem( 'first', 'second', 'third', 'fourth' ) --> first second third
In JS, you have a special arguments collection available holding all arguments. In Lua 5.0, this is a table called arg, but it only gathers any parameters where you have specified the special ... notation in the parameter list:
function showem( a, b, ... )
local output = tostring(a) .. "\t" .. tostring(b)
for i,v in ipairs(arg) do
output = output .. "\t#" .. i .. ":" .. v
end
print( output )
end
showem( 'first' ) --> first nil
showem( 'first', 'second' ) --> first second
showem( 'first', 'second', 'third' ) --> first second #1:third
showem( 'first', 'second', 'third', 'fourth' ) --> first second #1:third #2:fourth
In Lua 5.1, the arg table has been replaced with "vararg expressions":
function showem( a, b, ... )
local output = tostring(a) .. "\t" .. tostring(b)
local theArgs = { ... }
for i,v in ipairs( theArgs ) do
output = output .. "\t#" .. i .. ":" .. v
end
print( output )
end
showem( 'first' ) --> first nil
showem( 'first', 'second' ) --> first second
showem( 'first', 'second', 'third' ) --> first second #1:third
showem( 'first', 'second', 'third', 'fourth' ) --> first second #1:third #2:fourth
In JS and Lua, you can access a key in a hash either using bracket notation:
theage = gavin[ 'age' ]
or by using dot notation:
theage = gavin.age
In JS and Lua, there is no differentiation between integers and floats, nor separate types for different sizes of objects. All numeric representations in Lua are 'number' values.
In JS and Lua, the semicolon (;) is used to indicate the end of a statement. In both, they are optional at the end of a line.
In JS, the convention is to include the semicolon. In Lua, the convention is to leave off the semicolon.
In JS, if you are inside a function and assign a value to a previously-unseen variable, the variable will be local if the var keyword was used, and global otherwise:
function foo( )
{
var jim = "This variable is local to the foo function";
jam = "This variable is in global scope";
}
Similarly in Lua, the local keyword indicates a local variable, while omitting it indicates a global variable:
function foo( )
local jim = "This variable is local to the foo function";
jam = "This variable is in global scope";
end
local moniker = 'Gavin \'Wiki\' Kistner'; --> Gavin 'Wiki' Kistner
local moniker = "Gavin 'Wiki' Kistner"; --> Gavin 'Wiki' Kistner
local moniker = 'Gavin "Wiki" Kistner'; --> Gavin "Wiki" Kistner
local moniker = "Gavin \"Wiki\" Kistner"; --> Gavin "Wiki" Kistner
mytable = { }
mytable.squareit = function( x )
return x * x
end
thefunc = mytable.squareit
print( thefunc( 7 ) ) --> 49
In JS and Lua, function objects are closures. In short, this means that functions have access to the local variables present in the scope that the function was defined in, even after that scope 'disappears':
function MakeAdder( inBaseValue )
return function( inValueToAdd )
return inBaseValue + inValueToAdd
end
end
add10 = MakeAdder( 10 )
add30 = MakeAdder( 30 )
print( add10( 1 ) ) --> 11
print( add10( 6 ) ) --> 16
print( add30( 3 ) ) --> 33
In JS, a single-line comment starts with //.
In JS, a multi-line comment uses /* ... */ to wrap the contents. The first occurrence of */ inside the comment closes the comment.
The magic of Lua's multi-line comment is that you can enable or disable the entire multi-line comment block with the addition or subtraction of a single character:
-- This is a single line Lua comment
local jim = "This is not commented"
--[[
local foo = "This code is not active"
local bar = "Neither is this code line"
--]]
local jam = "This line is active"
---[[
local foo = "This code is ALSO active"
local bar = "because of the extra hyphen above"
--]]
Lua (like Ruby) is big on using the keyword end to close off a block. For example:
function foo( )
--my code here
end
if foo( ) then
--my code here
end
for i=0,1000 do
--my code here
end
In Lua, the 'empty' value is represented by the keyword nil, unlike JS's null.
In JavaScript, "" and 0 equate as false when used in conditionals. In Lua, only nil and false evaluate as false.
In JavaScript, the key values for objects are always strings. (In JS, myObj[11] is the same as myObj["11"].) In Lua, strings, numbers, and even tables are all distinct keys:
a = {}
b = {}
mytable = {}
mytable[1] = "The number one"
mytable["1"] = "The string one"
mytable[a] = "The empty table 'a'"
mytable[b] = "The empty table 'b'"
print( mytable["1"] ) --> The string one
print( mytable[1] ) --> The number one
print( mytable[b] ) --> The empty table 'b'
print( mytable[a] ) --> The empty table 'a'
In JS, there is an explicit Array class of objects. It's a basic Object (hash) that modifies a special length property when you set values that look like integers, and that also has special methods defined for it.
var myArray = new Array( 10 );
var myOtherArray = [ 1, 2, 3 ];
In Lua, tables are objects. Tables are prototypes. Tables are hashes. Tables are arrays. Tables tables tables.
An 'array' in Lua is a table that has integer properties that start at 1 (not 0!) and which are consecutively numbered, up to the first nil value. Table literals can be used to create arrays, by not specifying the key for each value:
people = { "Gavin", "Stephen", "Harold" }
-- the above is the exact same as:
people = { [1]="Gavin", [2]="Stephen", [3]="Harold" }
The table library has two methods for getting and setting the 'size' of a table-used-as-array directly, allowing you to have an 'array' with nil elements inside of it:
people = { "Gavin", "Stephen", "Harold" }
print( table.getn( people ) ) --> 3
people[ 10 ] = "Some Dude"
print( table.getn( people ) ) --> 3
print( people[ 10 ] ) --> "Some Dude"
for i=1,table.getn( people ) do
print( people[ i ] )
end
--> Gavin
--> Stephen
--> Harold
table.setn( people, 10 )
print( table.getn( people ) ) --> 10
for i=1,table.getn( people ) do
print( people[ i ] )
end
--> Gavin
--> Stephen
--> Harold
--> nil
--> nil
--> nil
--> nil
--> nil
--> Some Dude
In Lua, procedural programming is king. There is no myString.length property, nor is there a myString.toLowerCase( ) method. You gotta use the library functions:
mystring = "Hello World"
print( string.len( mystring ) ) --> 11
print( string.lower( mystring ) ) --> hello world
This is somewhat changed in 5.1
Sorry. There's no shorthands in Lua. Gotta be verbose.
local themessage = "Hello"
themessage = themessage .. " World"
local thecounter = 1
thecounter = thecounter + 1
The sweet a ? b : c syntax isn't available in Lua. However, the short-circuit guard boolean operators and and or will (mostly) do what you need:
local foo = ( math.random( ) > 0.5 ) and "It's big!" or "It's small!"
local numusers = 1
print( numusers .. " user" .. ( numusers == 1 and " is" or "s are" ) .. " online." )
--> 1 user is online.
numusers = 10
print( numusers .. " user" .. ( numusers == 1 and " is" or "s are" ) .. " online." )
--> 10 users are online.
Note that this is not a direct equivalent of a ternary expression in all cases.
The JavaScript code m = x ? y : z
will always set m
to y
if x
is true
(or "truthy").
However, the Lua code m = x and y or z
will set m
to y
only
if x
is true
and y
is something other than false
or nil
.
local x=true, y=false, z="oops"
if x then
print( y )
else
print( z )
end
--> false
print( x and y or z )
--> "oops"
Although you rarely see it, the above works just as well in JavaScript using the && and || operators.
It's even more dangerous there, though, since there are more "non-truthy" values, like the empty string ""
:
// The following JavaScript code will never work; it will always output an 's'.
var cats = 1;
console.log( "I have " + cats + " cat" + (cats==1 && "" || "s") + "." );
"I have 1 cats."
I'm too lazy to write more right now, but notable items: