Learning Lua/From JS

Know JavaScript, and want to learn Lua? Here's are some quick facts about the similarities and differences. See Learning Lua for more resources.

Similarities

Case Sensitive

Lua and JS are both case sensitive. true and false are boolean literal values, and completely different from True or TRUE.

Functions May Take a Variable Number of Arguments

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

Hashes Referenced by Bracket or Dot Notation

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

A Number is a Number

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.

Semicolons End Statements

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.

Global Variables by Default

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

Strings are Delimited by " or '

In JS and Lua, string literals are denoted using either single- or double-quotes (in pairs). Like JS (and unlike Ruby or PHP) there is no difference between them. Like JS, you may use a backslash to escape the delimiter inside the string:
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

First-class Functions

In JS and Lua, functions are first-class objects. This means that you can assign them to variables, pass them around, and call them using ():
mytable = { }
mytable.squareit = function( x )
  return x * x
end

thefunc = mytable.squareit
print( thefunc( 7 ) ) --> 49

Functions are Closures

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

Differences

Single and Multi-Line Comments

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"
--]]

An end to Braces

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

null is nil

In Lua, the 'empty' value is represented by the keyword nil, unlike JS's null.

nil and false are the only Non-Truth Values

In JavaScript, "" and 0 equate as false when used in conditionals. In Lua, only nil and false evaluate as false.

Any Value is a Table Key

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'

There is no Array

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

Numbers, Strings, and Tables are not OOP Objects

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

No ++, no +=

Sorry. There's no shorthands in Lua. Gotta be verbose.

local themessage = "Hello"
themessage = themessage .. " World"

local thecounter = 1
thecounter = thecounter + 1

No Ternary Operator

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."

Other Stuff

I'm too lazy to write more right now, but notable items: