Created
May 1, 2025 00:57
-
-
Save jweslley/e05156505491d664b8b0f7b2e4a9779a to your computer and use it in GitHub Desktop.
Minimalist Lua Tutorial (found somewhere in Internet)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Lua.lua | |
-- | |
-- # Minimalist Lua Tutorial | |
-- | |
print( "Hello, astronaut." ) | |
-- this is a comment, just ignore it. | |
-- How to download and build Lua on Linux: | |
-- | |
-- $ wget http://www.lua.org/ftp/lua-5.2.3.tar.gz | |
-- $ tar zxf lua-5.2.3.tar.gz | |
-- $ cd lua-5.2.3 | |
-- $ make linux test | |
-- | |
-- Run!!! | |
-- $ lua Lua.lua | |
-- Do you want to interact with the soil of Lua? | |
-- $ lua -i | |
-- Make it executable? | |
-- $ chmod a+rx Lua.lua | |
-- $ ./Lua.lua | |
io.write( "I am ", _VERSION, "!\n\n" ) | |
--[[ | |
this is | |
a random | |
multiline | |
comment | |
--]] | |
--[[ Rule #1: | |
Identifiers must start with a letter 'A to Z' | |
or 'a to z' or an undescore '_' followed by | |
zero or more letters, underscores, and digits. | |
--]] | |
--[[ Keywords: | |
and elseif function nil return while | |
break end if not then | |
do false in or true | |
else for local repeat until | |
--]] | |
--[[ Variables: | |
Global variables: All variables are considered global unless explicitly | |
declared as a local. | |
Local variables: When the type is specified as local for a variable then its | |
scope is limited with the functions inside their scope. | |
Table fields: This is a special type of variable that can hold anything | |
except nil including functions. | |
--]] | |
function variables() | |
-- Variable definition: | |
local a, b | |
-- Initialization: | |
a = 10 | |
b = 30 | |
c, d = 'a', 'b' | |
print( "value of a: ", a ) | |
print( "value of b: ", b ) | |
print( "value of c: ", c ) | |
print( "value of d: ", d ) | |
print() | |
-- Swapping of variables | |
a, b = b, a | |
print( "value of a: ", a ) | |
print( "value of b: ", b ) | |
print() | |
end | |
--[[ Types: | |
nil -> Lack of value. | |
boolean -> true or false. | |
number -> Represents real(double precision floating point) numbers. | |
string -> Represents array of characters | |
function -> Represents a method that is written in C or Lua. | |
userdata -> Represents arbitrary C data. | |
thread -> Represents independent threads of execution and it is used | |
to implement coroutines. | |
table -> Represent ordinary arrays, symbol tables, sets, records, graphs, | |
trees, etc. And implements associative arrays. | |
It can hold any value (except nil). | |
--]] | |
function types() | |
print( type( nil ) ) | |
print( type( true ) ) | |
print( type( false ) ) | |
print( type( 5.8 ) ) | |
print( type( "What is my type?" ) ) | |
print( type( print ) ) | |
print( type( type ) ) | |
print( type( {} ) ) | |
print( type( type( x ) ) ) | |
print() | |
end | |
--[[ | |
By default, all the variables will point to nil until they are assigned a value | |
or initialized. In Lua, zero and empty strings are considered to be true in case | |
of condition checks. Hence, you have to be careful when using Boolean operations. | |
--]] | |
--[[ Operators: | |
Arithmetic Operators: + - * / % ^ -(unary) | |
Relational Operatorns: == ~= > < >= <= | |
Logical Operators: and or not | |
Misc Operators: | |
.. -> Concatenates two strings. | |
# -> An unary operator that return the length of a string or table. | |
--]] | |
function operators() | |
print( 5 + 3 ) | |
print( 5 - 3 ) | |
print( 5 * 3 ) | |
print( 5 / 3 ) | |
print( 5 % 3 ) | |
print( 5 ^ 3 ) | |
print( -5 ) | |
print() | |
print( 1 == 1 ) | |
print( 1 == 0 ) | |
print( 1 ~= 1 ) | |
print( 1 ~= 0 ) | |
print( 1 < 1 ) | |
print( 1 < 0 ) | |
print( 1 > 1 ) | |
print( 1 > 0 ) | |
print( 1 <= 1 ) | |
print( 1 <= 0 ) | |
print( 1 >= 1 ) | |
print( 1 >= 0 ) | |
print() | |
print( true and true ) | |
print( true and false ) | |
print( false and true ) | |
print( false and false ) | |
print( true or true ) | |
print( true or false ) | |
print( false or true ) | |
print( false or false ) | |
print( not true ) | |
print( not false ) | |
print() | |
print( "passion".."fruit" ) | |
print( #{1,2,3,4,5} ) | |
print() | |
end | |
--[[ Operators Precedence in Lua | |
[Category] [Operator] [Associativity] | |
Unary | not # - | Right to left | |
Concatenation | .. | Right to left | |
Multiplicative | * / % | Left to right | |
Additive | + - | Left to right | |
Relational | < > <= >= == ~= | Left to right | |
Equality | == ~= | Left to right | |
Logical AND | and | Left to right | |
Logical OR | or | Left to right | |
--]] | |
--[[ Decision Making! ]] | |
function decision_making() | |
-- if-then | |
a = 30 | |
if( a < 20 ) | |
then | |
print( "a is less than 20" ) | |
end | |
-- if-then-else | |
if( a < 50) | |
then | |
print( "a is less than 50" ) | |
else | |
print( "as is NOT less than 50" ) | |
end | |
-- nested if-then-else | |
if( a > 40 ) | |
then | |
io.write( "a is more than 40 " ) | |
if ( a < 90 ) | |
then | |
io.write( "and less than 90." ) | |
else | |
io.write( "but not less than 90." ) | |
end | |
else | |
io.write( "a is not more than 40 " ) | |
if ( a < 90 ) | |
then | |
io.write( "but is less than 90." ) | |
else | |
io.write( "nor is less than 90. how???" ) | |
end | |
end | |
io.write( "\n\n" ) | |
end | |
--[[ Loops! ]] | |
function loops() | |
-- while | |
a = 10 | |
while( a < 20 ) | |
do | |
print( "a:", a ) | |
a = a + 1 | |
end | |
print() | |
-- for | |
for i = 10,1,-1 | |
do | |
print( "i:", i ) | |
end | |
print() | |
-- reapeat-until | |
b = 10 | |
repeat | |
print( "b:", b ) | |
b = b + 1 | |
until( b > 15 ) | |
print() | |
end | |
--[[ Functions! ]] | |
function functions() | |
-- function returning the max between two numbers | |
function max(a, b) | |
if ( a > b ) then | |
result = a | |
else | |
result = b | |
end | |
return result | |
end | |
-- calling a function | |
print( "The maximum of the two numbers is ", max( 10, 4 ) ) | |
print( "The maximum of the two numbers is ", max( 5, 6 ) ) | |
print() | |
-- assigning and passing functions | |
scandalous_print = function(param) | |
print( "The marvelous result is: ", param, "!!!!!" ) | |
end | |
function add(a, b, callback) | |
result = a + b | |
callback( result ) | |
end | |
add( 2, 5, scandalous_print ) | |
print() | |
-- function with variable argument | |
function average(...) | |
sum = 0 | |
local arg = {...} | |
for i, v in ipairs(arg) do | |
sum = sum + v | |
end | |
return sum / #arg | |
end | |
print( "The average is ", average( 10, 5, 3, 4, 5, 6 ) ) | |
print() | |
end | |
--[[ Arrays! ]] | |
function arrays() | |
-- ## One-Dimensional Array | |
-- Assigning and accessing | |
array = {"Minimalist", "Lua", "Tutorial"} | |
for i = 1, 4 do | |
print( array[i] ) | |
end | |
print() | |
--[[ | |
> When we try to access an element in a index that is not there in the array, | |
it returs nil. | |
> In Lua, indexing generally starts at index 1. But it is possible to create | |
objects at index 0 and below 0 as well. | |
]] | |
-- negative indexes | |
for i = -2, 2 do | |
array[i] = i * 2 | |
end | |
for i = -2, 2 do | |
print( array[i] ) | |
end | |
print() | |
-- ## Multi-Dimensional Array | |
-- Initializing the array | |
array = {} | |
for i = 1, 3 do | |
array[i] = {} | |
for j = 1, 3 do | |
array[i][j] = i*j | |
end | |
end | |
-- Acessing the array | |
for i = 1, 3 do | |
for j = 1, 3 do | |
io.write( array[i][j], " " ) | |
end | |
print() | |
end | |
print() | |
-- ## Multi-Dimensional Virtual Array | |
-- Initializing the array | |
array = {} | |
maxRows = 3 | |
maxColumns = 3 | |
for row = 0, maxRows-1 do | |
for col = 0, maxColumns-1 do | |
array[row*maxColumns+col] = row*maxColumns+col | |
end | |
end | |
-- Accessing the array | |
for row = 0, maxRows-1 do | |
for col = 0, maxColumns-1 do | |
io.write( array[row*maxColumns+col], " " ) | |
end | |
print() | |
end | |
print() | |
end | |
--[[ Iterators: | |
Iterator is a construct that enables you to traverse through the elements | |
of the so called collection or container. | |
In Lua, these collections often refer to tables, which are used to create | |
various data structures like array. | |
--]] | |
function iterators() | |
array = {"Minimalist", "Lua", "Tutorial"} | |
for key, value in ipairs(array) | |
do | |
print( key, value ) | |
end | |
print() | |
--[[ Stateless vs Stateful | |
In Lua we use functions to represent iterators. Based on the state | |
maintenance in these iterator functions, we have two main types: | |
--]] | |
--[[ 1. Stateless iterator | |
Iterator function that does not retain any state. | |
Each time the function is called, it returns the next element based only in | |
the variables sent to the function. | |
--]] | |
function square(iteratorMaxCount, currentNumber) | |
if currentNumber < iteratorMaxCount | |
then | |
currentNumber = currentNumber+1 | |
return currentNumber, currentNumber*currentNumber | |
end | |
end | |
function squares(iteratorMaxCount) | |
return square,iteratorMaxCount,0 | |
end | |
for i, n in squares( 3 ) | |
do | |
print( i, n ) | |
end | |
print() | |
--[[ 2. Stateful Iterator | |
To hold the state fo the current element, closures are used. Closure retain | |
variables values across functions calls. To create a new closure, we create | |
two functions including the closure itself and a factory, the function that | |
creates the closure. | |
--]] | |
function elementIterator(collection) | |
local index = 0 | |
local count = #collection | |
-- The closure function is returned | |
return function () | |
index = index + 1 | |
if index <= count | |
then | |
-- return the current element of the iterator | |
return collection[index] | |
end | |
end | |
end | |
for element in elementIterator(array) | |
do | |
print( element ) | |
end | |
print() | |
end | |
--[[ Strings! ]] | |
function strings() | |
string1 = "Lua" | |
print( string1 ) | |
string2 = 'Tutorial' | |
print( string2 ) | |
string3 = [[ | |
"lua | |
Tutorial" | |
]] | |
print( string3 ) | |
--[[ Escape sequences | |
\a : Bell | |
\b : Backspace | |
\f : Formfeed | |
\n : New line | |
\r : Carriage return | |
\t : Tab | |
\v : Vertical tab | |
\\ : Backslash | |
\" : Double quotes | |
\' : Single quotes | |
\[ : Left square bracket | |
\] : Rigth square bracket | |
]] | |
--[[ String Manipulation | |
string.upper( argument ) | |
Returns a capitalized representation of the argument. | |
string.lower( argument ) | |
Returns a lower case representation of the argument. | |
string.gsub( mainString, findString, replaceString ) | |
Returns a string by replacing occurrences of findString with replaceString. | |
string.find( mainString, findString, optionalStartIndex, optionalEndIndex ) | |
Returns the start index and end index of the findString in the main string and | |
nil if not found. | |
string.reverse( argument ) | |
Returns a string by reversing the characters of the passed string. | |
string.format( ... ) | |
Returns a formatted string. | |
string.char( argument ) | |
Returns character representation of input argument. | |
string.byte( argument ) | |
Returns internal numeric representation of input argument. | |
string.len( argument ) | |
Returns a length of the passed string. | |
string.rep( string, n ) | |
Returns a string by repeating the same string n number times. | |
]] | |
end | |
--[[ Tables | |
Tables are the only data structure available in Lua that helps us create | |
different types like arrays and dictionaries. lua uses associative arrays | |
and which can be indexed with not only numbers but also with strings | |
except nil. Tables have no fixed size and can grow based on our need. | |
Lua uses tables in all representations including representation of packages. | |
When we access a method string.format, it means, we are accessing the format | |
function available in the string package. | |
--]] | |
function tables() | |
-- table initialization | |
mytable = {} | |
-- table value assignment | |
mytable[1] = "Lua" | |
mytable['a'] = "Tutorial" | |
-- removing reference | |
mytable = nil | |
--[[ | |
When we have a table 'a' with set of elements and if we assign it to 'b', | |
both 'a' and 'b' refer to the same memory. | |
No separate memory is allocated separately for b. When a is set to nil, | |
table will be still accessible to b. When there are no reference to a table, | |
then garmag collection in Lua takes care of cleaning up process to make these | |
unreferenced memory to be reused again. | |
--]] | |
a_table = {} | |
print("Type of a_table is ", type(a_table)) | |
a_table[1] = "Lua" | |
a_table["wow"] = "Tutorial" | |
print( a_table[1] ) | |
print( a_table["wow"] ) | |
print() | |
b_table = a_table | |
a_table[0] = "Minimalist" | |
a_table = nil | |
print( b_table[0] ) | |
print( b_table[1] ) | |
print( b_table["wow"] ) | |
print() | |
b_table = nil | |
--[[ Table Manipulation | |
table.concat(table [, sep [, i [, j ] ] ]) | |
Concatenates the strings in the tables based on the parameters given. | |
See example for detail. | |
Somehow equivalent to join() in other languages. | |
table.insert(table, [pos,] value) | |
Inserts a value into the table at specified position | |
table.maxn(table) | |
Return the largest numeric index. | |
table.remove(table [, pos]) | |
Removes the value from tthe table. | |
table.sort(table [, comp]) | |
Sorts the table based on optional comparator argument. | |
--]] | |
fruits = {"banana","orange","apple", "strawberry"} | |
-- returns concatenated string of table | |
print( table.concat( fruits ) ) | |
-- return concatenate with a characters | |
print( table.concat( fruits, ", " ) ) | |
-- return fruits based on index | |
print( table.concat( fruits, ", ", 2, 3 ) ) | |
print() | |
function print_array(array) | |
print( table.concat( array, ", " ) ) | |
end | |
-- insert a fruit at the end | |
table.insert( fruits, "mango" ) | |
print_array( fruits ) | |
-- insert fruit at index 2 | |
table.insert( fruits, 2, "grapes" ) | |
print_array( fruits ) | |
-- Maximum element | |
print( table.maxn( fruits ) ) | |
-- Remove last fruit | |
table.remove( fruits ) | |
print_array( fruits ) | |
-- Remove fruit at index 2 | |
table.remove( fruits, 2 ) | |
print_array( fruits ) | |
print() | |
print("fruits:") | |
for k,v in ipairs(fruits) do | |
print( k, v ) | |
end | |
print() | |
table.sort( fruits ) | |
print("sorted fruits:") | |
for k,v in ipairs(fruits) do | |
print( k, v ) | |
end | |
print() | |
end | |
--[[ Metatables | |
A metatable is a table that helps in modifying the behavior of a table it is | |
attached to with the help of a key set and related meta methods. | |
These meta methods are powerful Lua functionality that enables features like: | |
> Changing/adding functionalities to operators on tables. | |
> Looking up metatables when the key is not available in the table using | |
__index in metatable. | |
There are two important methods that are used in handling metatables which | |
includes: | |
> setmatetable( table, metatable ) | |
> getmetatable( table ) | |
]] | |
function metatables() | |
-- __index | |
mytable = setmetatable( { key1 = "value1" }, { | |
__index = function(mytable, key) | |
if key == "key2" then | |
return "metatablevalue" | |
else | |
return mytable[key] | |
end | |
end | |
} ) | |
print( mytable.key1, mytable.key2 ) | |
print() | |
-- __newindex | |
mydeposittable = {} | |
mytable = setmetatable( { key1 = "value1" }, { __newindex = mydeposittable } ) | |
print( mytable.key1 ) | |
print() | |
mytable.newkey = "new value 2" | |
print( mytable.newkey ) | |
print( mydeposittable.newkey ) | |
print() | |
mytable.key1 = "new value 1" | |
print( mytable.key1 ) | |
print( mydeposittable.newkey1 ) | |
print() | |
--[[ if a key exists in the main table, it just updates it. | |
When a key is not available in the maintable, | |
it adds that key to the deposittable | |
]] | |
mytable = setmetatable( {key1 = "value1"}, { | |
__newindex = function(mytable, key, value) | |
rawset( mytable, key, "\""..value.."\"" ) | |
end | |
} ) | |
mytable.key1 = "new value" | |
mytable.key2 = 4 | |
print( mytable.key1 ) | |
print( mytable.key2 ) | |
print() | |
-- __add | |
mytable = setmetatable( { 1, 2, 3 }, { | |
__add = function(mytable, othertable) | |
for i = 1, table.maxn( othertable ) do | |
table.insert( mytable, table.maxn(mytable) + 1, othertable[i] ) | |
end | |
return mytable | |
end | |
} ) | |
secondtable = { 4, 5, 6 } | |
resulttable = mytable + secondtable | |
for k, v in ipairs( resulttable ) do | |
print( k, v ) | |
end | |
print() | |
--[[ | |
__add | |
Changes the behavior of operator '+'. | |
__sub | |
Changes the behavior of operator '-'. | |
__mul | |
Changes the behavior of the operator '*'. | |
__div | |
Changes the behavior of operator '/'. | |
__mod | |
Changes the behavior of operator '%'. | |
__unm | |
Changes the behavior of operator '-'. | |
__concat | |
Changes the behavior of operator '..'. | |
__eq | |
Changes the behavior of operator '=='. | |
__lt | |
Changes the behavior of operator '<'. | |
__le | |
Changes the behavior of operator '<='. | |
]] | |
-- __call | |
mytable = setmetatable( { 10, 20 }, { | |
__call = function(mytable, othertable) | |
sum = 0 | |
for i = 1, table.maxn(mytable) do | |
sum = sum + mytable[i] | |
end | |
for i = 1, table.maxn(othertable) do | |
sum = sum + othertable[i] | |
end | |
return sum | |
end | |
} ) | |
secondtable = { 10, 20, 30 } | |
print( mytable( secondtable ) ) | |
print() | |
end | |
function menu() | |
tests_array = { | |
variables, | |
types, | |
operators, | |
decision_making, | |
loops, | |
functions, | |
arrays, | |
iterators, | |
strings, | |
tables, | |
metatables | |
} | |
tests_dict = { | |
['variables'] = variables, | |
['types'] = types, | |
['operators'] = operators, | |
['decision making'] = decision_making, | |
['loops'] = loops, | |
['functions'] = functions, | |
['arrays'] = arrays, | |
['iterators'] = iterators, | |
['strings'] = strings, | |
['tables'] = tables, | |
['metatables'] = metatables | |
} | |
local input | |
repeat | |
print() | |
print( 'Choose the tests to run:' ) | |
print() | |
print( '1. Variables' ) | |
print( '2. Types' ) | |
print( '3. Operators' ) | |
print( '4. Decision making' ) | |
print( '5. Loops' ) | |
print( '6. Functions' ) | |
print( '7. Arrays' ) | |
print( '8. Iterators' ) | |
print( '9. Strings' ) | |
print( '10. Tables' ) | |
print( '11. Metatables' ) | |
print() | |
print( 'Enter the number or the name (or enter \'bye\' to exit).') | |
print() | |
io.write( '> ' ) | |
input = io.read() | |
if ( tests_array[tonumber( input )] ) | |
then | |
tests_array[tonumber( input )]() | |
elseif ( tests_dict[string.lower(input)] ) | |
then | |
tests_dict[string.lower(input)]() | |
elseif ( input == 'bye' ) | |
then | |
print( 'See you, astronaut!' ) | |
else | |
print( 'Invalid option!!' ) | |
end | |
until( input == 'bye' ) | |
end | |
menu() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment