class, module, coroutine, begining error
+ some correction and addition.
This commit is contained in:
parent
655ce78eee
commit
74b02df3c1
219
README.md
219
README.md
@ -1,6 +1,7 @@
|
|||||||
# cheat-sheet-lua
|
# cheat-sheet-lua
|
||||||
|
|
||||||
Here is the IO-Project cheat sheet to quickly learn the "Lua" programming language
|
Here is the IO-Project cheat sheet to quickly learn the "Lua" programming language.
|
||||||
|
I suggest you to consult the documentation of lua for more information on the language, it is available by following [this link](https://www.lua.org/manual/5.3/).
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
@ -8,7 +9,7 @@ Use this table of contents to travel more easily through this cheat sheet.
|
|||||||
|
|
||||||
- [cheat-sheet-lua](#cheat-sheet-lua)
|
- [cheat-sheet-lua](#cheat-sheet-lua)
|
||||||
- [Table of contents](#table-of-contents)
|
- [Table of contents](#table-of-contents)
|
||||||
- [The basics](#the-basics)
|
- [Basics](#basics)
|
||||||
- [Code comments](#code-comments)
|
- [Code comments](#code-comments)
|
||||||
- [Variables and loop](#variables-and-loop)
|
- [Variables and loop](#variables-and-loop)
|
||||||
- [Functions](#functions)
|
- [Functions](#functions)
|
||||||
@ -16,8 +17,13 @@ Use this table of contents to travel more easily through this cheat sheet.
|
|||||||
- [Tables, Array, dict..](#tables-array-dict)
|
- [Tables, Array, dict..](#tables-array-dict)
|
||||||
- [Metatables and metamethods](#metatables-and-metamethods)
|
- [Metatables and metamethods](#metatables-and-metamethods)
|
||||||
- [Class-like tables and inheritance.](#class-like-tables-and-inheritance)
|
- [Class-like tables and inheritance.](#class-like-tables-and-inheritance)
|
||||||
|
- [Coroutine](#coroutine)
|
||||||
|
- [Error handling](#error-handling)
|
||||||
|
- [Modules](#modules)
|
||||||
|
|
||||||
## The basics
|
## Basics
|
||||||
|
|
||||||
|
> We'll now introduce the basics of lua, starting with comments, variables, loops and functions.
|
||||||
|
|
||||||
### Code comments
|
### Code comments
|
||||||
|
|
||||||
@ -163,14 +169,13 @@ print 'hello' -- Works fine.
|
|||||||
|
|
||||||
## Advanced
|
## Advanced
|
||||||
|
|
||||||
|
> Let's move on to more advanced notions. With the notion of table, class, module, coroutine, meta-programming and module.
|
||||||
|
|
||||||
### Tables, Array, dict..
|
### Tables, Array, dict..
|
||||||
|
|
||||||
````lua
|
Tables are the only compound data structure in Lua, they are associative arrays. Similar to php arrays or js objects, they are hash-lookup dicts that can also be used as lists.
|
||||||
-- Tables = Lua's only compound data structure;
|
|
||||||
-- they are associative arrays.
|
|
||||||
-- Similar to php arrays or js objects, they are
|
|
||||||
-- hash-lookup dicts that can also be used as lists.
|
|
||||||
|
|
||||||
|
````lua
|
||||||
-- Using tables as dictionaries / maps:
|
-- Using tables as dictionaries / maps:
|
||||||
|
|
||||||
-- Dict literals have string keys by default:
|
-- Dict literals have string keys by default:
|
||||||
@ -218,11 +223,9 @@ end
|
|||||||
|
|
||||||
#### Metatables and metamethods
|
#### Metatables and metamethods
|
||||||
|
|
||||||
````lua
|
A table can have a metatable that gives the table operator-overloadish behavior. Later we'll see how metatables support js-prototypey behavior.
|
||||||
-- A table can have a metatable that gives the table
|
|
||||||
-- operator-overloadish behavior. Later we'll see
|
|
||||||
-- how metatables support js-prototypey behavior.
|
|
||||||
|
|
||||||
|
````lua
|
||||||
f1 = {a = 1, b = 2} -- Represents the fraction a/b.
|
f1 = {a = 1, b = 2} -- Represents the fraction a/b.
|
||||||
f2 = {a = 2, b = 3}
|
f2 = {a = 2, b = 3}
|
||||||
|
|
||||||
@ -282,4 +285,194 @@ eatenBy = myFavs.animal -- works! thanks, metatable
|
|||||||
-- __call(a, ...) for a(...)
|
-- __call(a, ...) for a(...)
|
||||||
````
|
````
|
||||||
|
|
||||||
#### Class-like tables and inheritance.
|
#### Class-like tables and inheritance.
|
||||||
|
|
||||||
|
Classes aren't built in, there are different ways to emulate them with tables and metatables.
|
||||||
|
The different ways to define a class in Lua are not easy to understand, so I suggest you to look at the [following document](support/class.lua) implementing 3 types of class definition. The last one being the one I chose (my preferred method).
|
||||||
|
|
||||||
|
````lua
|
||||||
|
-- Explanation for this example is below it.
|
||||||
|
Dog = {} -- 1.
|
||||||
|
|
||||||
|
function Dog:new() -- 2.
|
||||||
|
newObj = {sound = 'woof'} -- 3.
|
||||||
|
self.__index = self -- 4.
|
||||||
|
return setmetatable(newObj, self) -- 5.
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dog:makeSound() -- 6.
|
||||||
|
print('I say ' .. self.sound)
|
||||||
|
end
|
||||||
|
|
||||||
|
mrDog = Dog:new() -- 7.
|
||||||
|
mrDog:makeSound() -- 'I say woof' -- 8.
|
||||||
|
|
||||||
|
-- 1. Dog acts like a class; it's really a table.
|
||||||
|
-- 2. function tablename:fn(...) is the same as
|
||||||
|
-- function tablename.fn(self, ...)
|
||||||
|
-- The : just adds a first arg called self.
|
||||||
|
-- Read 7 & 8 below for how self gets its value.
|
||||||
|
-- 3. newObj will be an instance of class Dog.
|
||||||
|
-- 4. self = the class being instantiated. Often
|
||||||
|
-- self = Dog, but inheritance can change it.
|
||||||
|
-- newObj gets self's functions when we set both
|
||||||
|
-- newObj's metatable and self's __index to self.
|
||||||
|
-- 5. Reminder: setmetatable returns its first arg.
|
||||||
|
-- 6. The : works as in 2, but this time we expect
|
||||||
|
-- self to be an instance instead of a class.
|
||||||
|
-- 7. Same as Dog.new(Dog), so self = Dog in new().
|
||||||
|
-- 8. Same as mrDog.makeSound(mrDog); self = mrDog.
|
||||||
|
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
-- Inheritance example:
|
||||||
|
LoudDog = Dog:new() -- 1.
|
||||||
|
|
||||||
|
function LoudDog:makeSound()
|
||||||
|
s = self.sound .. ' ' -- 2.
|
||||||
|
print(s .. s .. s)
|
||||||
|
end
|
||||||
|
|
||||||
|
seymour = LoudDog:new() -- 3.
|
||||||
|
seymour:makeSound() -- 'woof woof woof' -- 4.
|
||||||
|
|
||||||
|
-- 1. LoudDog gets Dog's methods and variables.
|
||||||
|
-- 2. self has a 'sound' key from new(), see 3.
|
||||||
|
-- 3. Same as LoudDog.new(LoudDog), and converted to
|
||||||
|
-- Dog.new(LoudDog) as LoudDog has no 'new' key,
|
||||||
|
-- but does have __index = Dog on its metatable.
|
||||||
|
-- Result: seymour's metatable is LoudDog, and
|
||||||
|
-- LoudDog.__index = LoudDog. So seymour.key will
|
||||||
|
-- = seymour.key, LoudDog.key, Dog.key, whichever
|
||||||
|
-- table is the first with the given key.
|
||||||
|
-- 4. The 'makeSound' key is found in LoudDog; this
|
||||||
|
-- is the same as LoudDog.makeSound(seymour).
|
||||||
|
|
||||||
|
-- If needed, a subclass's new() is like the base's:
|
||||||
|
function LoudDog:new()
|
||||||
|
newObj = {}
|
||||||
|
-- set up newObj
|
||||||
|
self.__index = self
|
||||||
|
return setmetatable(newObj, self)
|
||||||
|
end
|
||||||
|
````
|
||||||
|
|
||||||
|
### Coroutine
|
||||||
|
|
||||||
|
Let's turn now to coroutines. Coroutines are functions that can be suspended and resumed at a later time. They are used to implement iterators, generators and event loops and represent a line of execution with its own stack. In other words, they can be compared to threads.
|
||||||
|
|
||||||
|
````lua
|
||||||
|
-- Create a coroutine that prints 'Hello' and then stops.
|
||||||
|
coHi = coroutine.create(function () print('Hello') end)
|
||||||
|
print(coHi) -- thread: 0x7f9c0c00a0c0
|
||||||
|
|
||||||
|
-- Coroutine status can be 'suspended', 'running' or 'dead'.
|
||||||
|
-- The coroutine is created in the 'suspended' state.
|
||||||
|
|
||||||
|
-- Resume the coroutine. It will print 'Hello' and stop.
|
||||||
|
coroutine.resume(coHi) -- return 'true'
|
||||||
|
print(coroutine.status(coHi)) -- 'dead'
|
||||||
|
|
||||||
|
-- We can also pass arguments to the coroutine.
|
||||||
|
-- The arguments of the first resume are passed to the
|
||||||
|
-- function of the coroutine. The following arguments
|
||||||
|
-- are passed to the yield function.
|
||||||
|
routine = coroutine.create(function (a, b, c)
|
||||||
|
print('first print: ', a, b, c)
|
||||||
|
print('yield1: ', coroutine.yield())
|
||||||
|
print('yield2: ', coroutine.yield('a variable'))
|
||||||
|
return(a+b+c)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- will run the coroutine until the first yield.
|
||||||
|
coroutine.resume(routine, 1, 2, 3)
|
||||||
|
-- run the coroutine until the second yield passing
|
||||||
|
-- the arguments 4, 5 and 6 to the 1er yield and
|
||||||
|
-- retrieve the return value of the second yield.
|
||||||
|
print('out routine: ' , coroutine.resume(routine, 4, 5, 6))
|
||||||
|
-- this will run out the second yield and made the
|
||||||
|
-- adition of 'a+b+c' and kill the coroutine.
|
||||||
|
print(coroutine.resume(routine, 7, 8, 9)) -- 1+2+3 = '6'
|
||||||
|
|
||||||
|
-- All these steps will print:
|
||||||
|
--[[
|
||||||
|
first print: 1 2 3
|
||||||
|
yield1: 4 5 6
|
||||||
|
out routine: true a variable
|
||||||
|
yield2: 7 8 9
|
||||||
|
true 6
|
||||||
|
--]]
|
||||||
|
````
|
||||||
|
|
||||||
|
### Error handling
|
||||||
|
|
||||||
|
Lua allows low-level error handling with the `error` function and high-level error handling with the `assert` function. The `error` function raises an error and handles it with the `pcall` or `xpcall` function. The `assert` function checks a condition and raises an error if the condition is not met.
|
||||||
|
|
||||||
|
````lua
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Throw an error if the first argument is false
|
||||||
|
-- the second argument is the error message.
|
||||||
|
assert(type(firstvariable) = 'string', 'not a string')
|
||||||
|
|
||||||
|
-- TODO to continue
|
||||||
|
|
||||||
|
````
|
||||||
|
|
||||||
|
### Modules
|
||||||
|
|
||||||
|
Modules are a way to organize your code. They are a way to group functions and variables together in a single file. You can then use the module in other files by using the `require` function.
|
||||||
|
|
||||||
|
````lua
|
||||||
|
-- Suppose the file mod.lua looks like this:
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
local function sayMyName()
|
||||||
|
print('Hrunkner')
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.sayHello()
|
||||||
|
print('Why hello there')
|
||||||
|
sayMyName()
|
||||||
|
end
|
||||||
|
|
||||||
|
return M -- Return the table M.
|
||||||
|
|
||||||
|
-- Another file can use mod.lua's functionality:
|
||||||
|
local mod = require('mod') -- Run the file mod.lua.
|
||||||
|
|
||||||
|
-- require is the standard way to include modules.
|
||||||
|
-- require acts like: (if not cached; see below)
|
||||||
|
local mod = (function ()
|
||||||
|
<contents of mod.lua>
|
||||||
|
end)()
|
||||||
|
-- It's like mod.lua is a function body, so that
|
||||||
|
-- locals inside mod.lua are invisible outside it.
|
||||||
|
|
||||||
|
-- This works because mod here = M in mod.lua:
|
||||||
|
mod.sayHello() -- Says hello to Hrunkner.
|
||||||
|
|
||||||
|
-- This is wrong, sayMyName only exists in mod.lua:
|
||||||
|
mod.sayMyName() -- error
|
||||||
|
|
||||||
|
-- require's return values are cached so a file is
|
||||||
|
-- run at most once, even when require'd many times.
|
||||||
|
|
||||||
|
-- Suppose mod2.lua contains "print('Hi!')".
|
||||||
|
local a = require('mod2') -- Prints Hi!
|
||||||
|
local b = require('mod2') -- Doesn't print; a=b.
|
||||||
|
|
||||||
|
-- dofile is like require without caching:
|
||||||
|
dofile('mod2.lua') --> Hi!
|
||||||
|
dofile('mod2.lua') --> Hi! (runs it again)
|
||||||
|
|
||||||
|
-- loadfile loads a lua file but doesn't run it yet.
|
||||||
|
f = loadfile('mod2.lua') -- Call f() to run it.
|
||||||
|
|
||||||
|
-- loadstring is loadfile for strings.
|
||||||
|
g = loadstring('print(343)') -- Returns a function.
|
||||||
|
g() -- Prints out '343', nothing printed before now.
|
||||||
|
|
||||||
|
````
|
||||||
|
|
||||||
|
102
support/class.lua
Normal file
102
support/class.lua
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- This is a simple Person class (Raw example without synthetic sugar).
|
||||||
|
-- ============================================================================
|
||||||
|
Person1 = {}
|
||||||
|
|
||||||
|
-- Constructor
|
||||||
|
function Person1.new(self, name, age)
|
||||||
|
local o = {}
|
||||||
|
self.__index = self
|
||||||
|
setmetatable(o, self)
|
||||||
|
o.name = name
|
||||||
|
o.age = age
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Methods
|
||||||
|
function Person1.getName(self)
|
||||||
|
return self.name
|
||||||
|
end
|
||||||
|
|
||||||
|
function Person1.getAge(self)
|
||||||
|
return self.age
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Usage
|
||||||
|
local instance = Person1.new(Person1, "John", 30)
|
||||||
|
print('name: ' .. instance.getName(instance)) -- John
|
||||||
|
print('age: ' .. instance.getAge(instance)) -- 30
|
||||||
|
|
||||||
|
-- Garbage collection
|
||||||
|
Person1 = nil
|
||||||
|
instance = nil
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- This is a simple Person class (Synthetic sugar example).
|
||||||
|
-- ============================================================================
|
||||||
|
Person2 = {}
|
||||||
|
|
||||||
|
-- Constructor
|
||||||
|
function Person2:new(name, age)
|
||||||
|
local o = {}
|
||||||
|
self.__index = self
|
||||||
|
setmetatable(o, self)
|
||||||
|
o.name = name
|
||||||
|
o.age = age
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Methods
|
||||||
|
function Person2:getName()
|
||||||
|
return self.name
|
||||||
|
end
|
||||||
|
|
||||||
|
function Person2:getAge()
|
||||||
|
return self.age
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Usage
|
||||||
|
local instance = Person2:new("John Doe", 50)
|
||||||
|
print('name: ' .. instance:getName()) -- John Doe
|
||||||
|
print('age: ' .. instance:getAge()) -- 50
|
||||||
|
|
||||||
|
-- Garbage collection
|
||||||
|
Person2 = nil
|
||||||
|
instance = nil
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- This is my class definition method (with Synthetic sugar example).
|
||||||
|
-- ============================================================================
|
||||||
|
Person = {}
|
||||||
|
|
||||||
|
-- Constructor
|
||||||
|
function Person:new(name, age)
|
||||||
|
local this = setmetatable({}, {__index = self})
|
||||||
|
this.name = name or 'EndMove'
|
||||||
|
this.age = age or 20
|
||||||
|
return this
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Methods
|
||||||
|
function Person:getFName()
|
||||||
|
return 'name: ' .. self.name
|
||||||
|
end
|
||||||
|
|
||||||
|
function Person:getFAge()
|
||||||
|
return 'age: ' .. self.age
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Usage
|
||||||
|
local instance = Person:new("Gashy", 21)
|
||||||
|
print(instance:getFName()) -- name: Gashy
|
||||||
|
print(instance:getFAge()) -- age: 21
|
||||||
|
|
||||||
|
-- Garbage collection
|
||||||
|
Person = nil
|
||||||
|
instance = nil
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Thanks for reading!
|
@ -1,3 +1,8 @@
|
|||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Let's study the different loops offered by the Lua language.
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
-- Jeb while loop
|
-- Jeb while loop
|
||||||
local jebSum = 0
|
local jebSum = 0
|
||||||
print('jeb : '..jebSum)
|
print('jeb : '..jebSum)
|
||||||
@ -38,4 +43,7 @@ while true do
|
|||||||
print('Breaking out in')
|
print('Breaking out in')
|
||||||
if true then break end
|
if true then break end
|
||||||
end
|
end
|
||||||
print('Breaking out -> Done')
|
print('Breaking out -> Done')
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Thanks for reading!
|
Loading…
Reference in New Issue
Block a user