Lua originated in 1993 as a language for extendingsoftware applications to meet the increasing demand for customization at the time. It provided the basic facilities of mostprocedural programming languages, but more complicated ordomain-specific features were not included; rather, it included mechanisms for extending the language, allowing programmers to implement such features. As Lua was intended to be a general embeddable extension language, the designers of Lua focused on improving itsspeed,portability, extensibility and ease-of-use in development.
From 1977 until 1992, Brazil had a policy of strongtrade barriers (called a market reserve) forcomputer hardware andsoftware, believing that Brazil could and should produce its own hardware and software. In that climate, Tecgraf's clients could not afford, either politically or financially, to buy customized software from abroad; under the market reserve, clients would have to go through a complex bureaucratic process to prove their needs couldn't be met by Brazilian companies. Those reasons led Tecgraf to implement the basic tools it needed from scratch.[6]
Lua's predecessors were the data-description and configuration languages Simple Object Language (SOL) and Data-Entry Language (DEL).[7] They had been independently developed at Tecgraf in 1992–1993 to add some flexibility into two different projects (both were interactive graphical programs for engineering applications atPetrobras company). There was a lack of any flow-control structures in SOL and DEL, and Petrobras felt a growing need to add full programming power to them.
InThe Evolution of Lua, the language's authors wrote:[6]
In 1993, the only real contender wasTcl, which had been explicitly designed to be embedded into applications. However, Tcl had unfamiliar syntax, did not offer good support for data description, and ran only on Unix platforms. We did not considerLISP orScheme because of their unfriendly syntax.Python was still in its infancy. In the free, do-it-yourself atmosphere that then reigned in Tecgraf, it was quite natural that we should try to develop our own scripting language ... Because many potential users of the language were not professional programmers, the language should avoid cryptic syntax and semantics. The implementation of the new language should be highly portable, because Tecgraf's clients had a very diverse collection of computer platforms. Finally, since we expected that other Tecgraf products would also need to embed a scripting language, the new language should follow the example of SOL and be provided as a library with a C API.
Lua 1.0 was designed in such a way that its object constructors, being then slightly different from the current light and flexible style, incorporated the data-description syntax of SOL (hence the name Lua:Sol meaning "Sun" in Portuguese, andLua meaning "Moon"). Luasyntax for control structures was mostly borrowed fromModula (if,while,repeat/until), but also had taken influence fromCLU (multiple assignments and multiple returns from function calls, as a simpler alternative toreference parameters or explicitpointers),C++ ("neat idea of allowing alocal variable to be declared only where we need it"[6]),SNOBOL andAWK (associative arrays). In an article published inDr. Dobb's Journal, Lua's creators also state that LISP and Scheme with their single, ubiquitous data-structure mechanism (thelist) were a major influence on their decision to develop the table as the primary data structure of Lua.[8]
Luasemantics have been increasingly influenced by Scheme over time,[6] especially with the introduction ofanonymous functions and fulllexical scoping. Several features were added in new Lua versions.
Versions of Lua prior to version 5.0 were released under a license similar to theBSD license. From version 5.0 onwards, Lua has been licensed under theMIT License. Both arepermissive free software licences and are almost identical.
In general, Lua strives to provide simple, flexiblemeta-features that can be extended as needed, rather than supply a feature-set specific to one programming paradigm. As a result, the base language islight; the full referenceinterpreter is only about 247 kB compiled[4] and easily adaptable to a broad range of applications.
As adynamically typed language intended for use as an extension language orscripting language, Lua is compact enough to fit on a variety of host platforms. It supports only a small number of atomic data structures such asBoolean values, numbers (double-precisionfloating point and64-bitintegers by default) andstrings. Typical data structures such asarrays,sets,lists andrecords can be represented using Lua's single native data structure, the table, which is essentially a heterogeneousassociative array.
Acomment in Lua starts with a double-hyphen and runs to the end of the line, similar toAda,Eiffel,Haskell,SQL andVHDL. Multi-line strings and comments are marked with double square brackets.
-- Single line comment--[[Multi-line comment--]]
Thefactorial function is implemented in this example:
ifx==ythenprint("x = y")elseifx==zthenprint("x = z")else-- optionalprint("x does not equal any other variable")end
Lua has four types of conditional loops: thewhile loop, therepeat loop (similar to ado while loop), the numericfor loop and the genericfor loop.
--condition = truewhileconditiondo--statementsendrepeat--statementsuntilconditionfori=first,last,deltado--delta may be negative, allowing the for loop to count down or up--statements--example: print(i)end
This genericfor loop would iterate over the table_G using the standard iterator functionpairs, until it returnsnil:
forkey,valueinpairs(_G)doprint(key,value)end
Loops can also benested (put inside of another loop).
Lua's treatment of functions asfirst-class values is shown in the following example, where the print function's behavior is modified:
dolocaloldprint=print-- Store current print function as oldprintfunctionprint(s)--[[ Redefine print function. The usual print function can still be used through oldprint. The new one has only one argument.]]oldprint(s=="foo"and"bar"ors)endend
Any future calls toprint will now be routed through the new function, and because of Lua'slexical scoping, the old print function will only be accessible by the new, modified print.
functionaddto(x)-- Return a new function that adds x to the argumentreturnfunction(y)--[[ When we refer to the variable x, which is outside the current scope and whose lifetime would be shorter than that of this anonymous function, Lua creates a closure.]]returnx+yendendfourplus=addto(4)print(fourplus(3))-- Prints 7--This can also be achieved by calling the function in the following way:print(addto(4)(3))--[[ This is because we are calling the returned function from 'addto(4)' with the argument '3' directly. This also helps to reduce data cost and up performance if being called iteratively.]]
A new closure for the variablex is created every timeaddto is called, so that each new anonymous function returned will always access its ownx parameter. The closure is managed by Lua's garbage collector, just like any other object.
Tables are the most important data structures (and, by design, the only built-incomposite data type) in Lua and are the foundation of all user-created types. They are associative arrays with addition of automatic numeric key and special syntax.
A table is a set of key and data pairs, where the data is referenced by key; in other words, it is ahashed heterogeneous associative array.
Tables are created using the{} constructor syntax.
A key (index) can be any value exceptnil andNaN, including functions.
a_table={x=10}-- Creates a new table, with one entry mapping "x" to the number 10.print(a_table["x"])-- Prints the value associated with the string key, in this case 10.b_table=a_tableb_table["x"]=20-- The value in the table has been changed to 20.print(b_table["x"])-- Prints 20.print(a_table["x"])-- Also prints 20, because a_table and b_table both refer to the same table.
A table is often used asstructure (orrecord) by usingstrings as keys. Because such use is very common, Lua features a special syntax for accessing such fields.[11]
point={x=10,y=20}-- Create new tableprint(point["x"])-- Prints 10print(point.x)-- Has exactly the same meaning as line above. The easier-to-read dot notation is just syntactic sugar.
By using a table to store related functions, it can act as a namespace.
Tables are automatically assigned a numerical key, enabling them to be used as anarray data type. The first automatic index is 1 rather than 0 as it is for many other programming languages (though an explicit index of 0 is allowed).
A numeric key1 is distinct from a string key"1".
array={"a","b","c","d"}-- Indices are assigned automatically.print(array[2])-- Prints "b". Automatic indexing in Lua starts at 1.print(#array)-- Prints 4. # is the length operator for tables and strings.array[0]="z"-- Zero is a legal index.print(#array)-- Still prints 4, as Lua arrays are 1-based.
The length of a tablet is defined to be any integer indexn such thatt[n] is notnil andt[n+1] isnil; moreover, ift[1] isnil,n can be zero. For a regular array, with non-nil values from 1 to a givenn, its length is exactly thatn, the index of its last value. If the array has "holes" (that is, nil values between other non-nil values), then#t can be any of the indices that directly precedes anil value (that is, it may consider any such nil value as the end of the array).[12]
ExampleTable={{1,2,3,4},{5,6,7,8}}print(ExampleTable[1][3])-- Prints "3"print(ExampleTable[2][4])-- Prints "8"
A table can be an array of objects.
functionPoint(x,y)-- "Point" object constructorreturn{x=x,y=y}-- Creates and returns a new object (table)endarray={Point(10,20),Point(30,40),Point(50,60)}-- Creates array of points-- array = { { x = 10, y = 20 }, { x = 30, y = 40 }, { x = 50, y = 60 } };print(array[2].y)-- Prints 40
Using a hash map to emulate an array is normally slower than using an actual array; however, Lua tables are optimized for use as arrays to help avoid this issue.[13]
Extensible semantics is a key feature of Lua, and the metatable allows powerful customization of tables. The following example demonstrates an "infinite" table. For anyn,fibs[n] will give then-thFibonacci number usingdynamic programming andmemoization.
fibs={1,1}-- Initial values for fibs[1] and fibs[2].setmetatable(fibs,{__index=function(values,n)--[[__index is a function predefined by Lua, it is called if key "n" does not exist.]]values[n]=values[n-1]+values[n-2]-- Calculate and memoize fibs[n].returnvalues[n]end})
Although Lua does not have a built-in concept ofclasses,object-oriented programming can be emulated using functions and tables. An object is formed by putting methods and fields in a table.Inheritance (both single and multiple) can be implemented withmetatables, delegating nonexistent methods and fields to a parent object.
There is no such concept as "class" with these techniques; rather,prototypes are used, similar toSelf orJavaScript. New objects are created either with afactory method (that constructs new objects from scratch) or by cloning an existing object.
localVector={}localVectorMeta={__index=Vector}functionVector.new(x,y,z)-- The constructorreturnsetmetatable({x=x,y=y,z=z},VectorMeta)endfunctionVector.magnitude(self)-- Another methodreturnmath.sqrt(self.x^2+self.y^2+self.z^2)endlocalvec=Vector.new(0,1,0)-- Create a vectorprint(vec.magnitude(vec))-- Call a method (output: 1)print(vec.x)-- Access a member variable (output: 0)
Here,setmetatable tells Lua to look for an element in theVector table if it is not present in thevec table.vec.magnitude, which is equivalent tovec["magnitude"], first looks in thevec table for themagnitude element. Thevec table does not have amagnitude element, but its metatable delegates to theVector table for themagnitude element when it's not found in thevec table.
Lua provides somesyntactic sugar to facilitate object orientation. To declaremember functions inside a prototype table, one can usefunctiontable:func(args), which is equivalent tofunctiontable.func(self,args). Calling class methods also makes use of the colon:object:func(args) is equivalent toobject.func(object,args).
That in mind, here is a corresponding class with: syntactic sugar:
localVector={}Vector.__index=VectorfunctionVector:new(x,y,z)-- The constructor-- Since the function definition uses a colon,-- its first argument is "self" which refers-- to "Vector"returnsetmetatable({x=x,y=y,z=z},self)endfunctionVector:magnitude()-- Another method-- Reference the implicit object using selfreturnmath.sqrt(self.x^2+self.y^2+self.z^2)endlocalvec=Vector:new(0,1,0)-- Create a vectorprint(vec:magnitude())-- Call a method (output: 1)print(vec.x)-- Access a member variable (output: 0)
It is possible to use metatables to mimic the behavior of class inheritance in Lua.[14] In this example, we allow vectors to have their values multiplied by a constant in a derived class.
localVector={}Vector.__index=VectorfunctionVector:new(x,y,z)-- The constructor-- Here, self refers to whatever class's "new"-- method we call. In a derived class, self will-- be the derived class; in the Vector class, self-- will be Vectorreturnsetmetatable({x=x,y=y,z=z},self)endfunctionVector:magnitude()-- Another method-- Reference the implicit object using selfreturnmath.sqrt(self.x^2+self.y^2+self.z^2)end-- Example of pseudo class inheritancelocalVectorMult={}VectorMult.__index=VectorMultsetmetatable(VectorMult,Vector)-- Make VectorMult a child of VectorfunctionVectorMult:multiply(value)self.x=self.x*valueself.y=self.y*valueself.z=self.z*valuereturnselfendlocalvec=VectorMult:new(0,1,0)-- Create a vectorprint(vec:magnitude())-- Call a method (output: 1)print(vec.y)-- Access a member variable (output: 1)vec:multiply(2)-- Multiply all components of vector by 2print(vec.y)-- Access member again (output: 2)
It is also possible to implementmultiple inheritance;__index can either be a function or a table.[15]Operator overloading can also be done; Lua metatables can have elements such as__add,__sub and so on.[16]
Lua programs are notinterpreted directly from the textual Lua file, but arecompiled into bytecode, which is then run on the Luavirtual machine (VM). The compiling process is typically invisible to the user and is performed duringrun-time, especially when ajust-in-time compilation (JIT) compiler is used, but it can be done offline to increase loading performance or reduce the memory footprint of the host environment by leaving out the compiler. Lua bytecode can also be produced and executed from within Lua, using thedump function from the string library and theload/loadstring/loadfile functions. Lua version 5.3.4 is implemented in approximately 24,000 lines of C code.[3][4]
Like most CPUs, and unlike most virtual machines (which arestack-based), the Lua VM isregister-based, and therefore more closely resembles most hardware design. The register architecture both avoids excessive copying of values, and reduces the total number of instructions per function. The virtual machine of Lua 5 is one of the first register-based pure VMs to have a wide use.[17]Parrot andAndroid'sDalvik are two other well-known register-based VMs. PCScheme's VM was also register-based.[18]
This example is the bytecode listing of the factorial function definedabove (as shown by theluac 5.1 compiler):[19]
Lua is intended to be embedded into other applications, and provides aCAPI for this purpose. The API is divided into two parts: the Lua core and the Lua auxiliary library.[20] The Lua API's design eliminates the need for manualreference counting (management) in C code, unlikePython's API. The API, like the language, is minimalist. Advanced functions are provided by the auxiliary library, which consists largely ofpreprocessormacros which assist with complex table operations.
The Lua C API isstack based. Lua provides functions to push and pop most simple C data types (integers, floats, etc.) to and from the stack, and functions to manipulate tables through the stack. The Lua stack is somewhat different from a traditional stack; the stack can be indexed directly, for example. Negative indices indicate offsets from the top of the stack. For example, −1 is the top (most recently pushed value), while positive indices indicate offsets from the bottom (oldest value).Marshalling data between C and Lua functions is also done using the stack. To call a Lua function, arguments are pushed onto the stack, and then thelua_call is used to call the actual function. When writing a C function to be directly called from Lua, the arguments are read from the stack.
Here is an example of calling a Lua function from C:
#include<stdio.h>#include<lua.h> // Lua main library (lua_*)#include<lauxlib.h> // Lua auxiliary library (luaL_*)intmain(void){// create a Lua statelua_State*L=luaL_newstate();// load and execute a stringif(luaL_dostring(L,"function foo (x,y) return x+y end")){lua_close(L);return-1;}// push value of global "foo" (the function defined above)// to the stack, followed by integers 5 and 3lua_getglobal(L,"foo");lua_pushinteger(L,5);lua_pushinteger(L,3);lua_call(L,2,1);// call a function with two arguments and one return valueprintf("Result: %d\n",lua_tointeger(L,-1));// print integer value of item at stack toplua_pop(L,1);// return stack to original statelua_close(L);// close Lua statereturn0;}
Running this example gives:
$cc-oexampleexample.c-llua$./exampleResult: 8
The C API also provides some special tables, located at various "pseudo-indices" in the Lua stack. AtLUA_GLOBALSINDEX prior to Lua 5.2[21] is the globals table,_G from within Lua, which is the mainnamespace. There is also a registry located atLUA_REGISTRYINDEX where C programs can store Lua values for later retrieval.
Besides standard library (core) modules it is possible to write extensions using the Lua API. Extension modules areshared objects which can be used to extend the functions of the interpreter by providing native facilities to Lua scripts. Lua scripts may load extension modules usingrequire,[20] just like modules written in Lua itself, or withpackage.loadlib.[22] When a C library is loaded viarequire('foo') Lua will look for the functionluaopen_foo and call it, which acts as any C function callable from Lua and generally returns a table filled with methods. A growing set of modules termedrocks are available through apackage management system namedLuaRocks,[23] in the spirit ofCPAN,RubyGems andPython eggs. Prewritten Luabindings exist for most popular programming languages, including other scripting languages.[24] For C++, there are a number of template-based approaches and some automatic binding generators.
In 2003, a poll conducted by GameDev.net showed that Lua was the most popular scripting language for game programming.[31] On 12 January 2012, Lua was announced as a winner of the Front Line Award 2011 from the magazineGame Developer in the category Programming Tools.[32]
Luau developed byRoblox Corporation, a derivative of and backwards-compatible with Lua 5.1 withgradual typing, additional features, and a focus on performance.[41] Luau has improved sandboxing to allow for running untrusted code in embedded applications.[42]
Ravi, a JIT-enabled Lua 5.3 language with optional static typing. JIT is guided by type information.[43]
Shine, a fork ofLuaJIT with many extensions, including a module system and a macro system.[44]
Glua, a modified version embedded into the gameGarry's Mod as its scripting language.[45]
^Ierusalimschy, Roberto; de Figueiredo, Luiz Henrique; Celes, Waldemar (2011–2013).Changes in the API. Lua.org. Retrieved9 May 2014.{{cite book}}:|work= ignored (help)
^Ierusalimschy, Roberto; de Figueiredo, Luiz Henrique; Celes, Waldemar."Lua 5.4 Reference Manual".Lua. Retrieved1 June 2022.
^"Poll Results". Archived from the original on 7 December 2003. Retrieved22 April 2017.{{cite web}}: CS1 maint: bot: original URL status unknown (link)
^"Why Luau?".Luau. Retrieved3 August 2024.All of these motivated us to start reshaping Lua 5.1 that we started from into a new, derivative language that we call Luau. Our focus is on making the language more performant and feature-rich, and make it easier to write robust code through a combination of linting and type checking using a gradual type system.