class, module, coroutine, begining error

+ some correction and addition.
This commit is contained in:
Jérémi N ‘EndMove’ 2023-01-16 00:47:06 +01:00
parent 655ce78eee
commit 74b02df3c1
Signed by: EndMove
GPG Key ID: 65C4A02E1F5371A4
3 changed files with 317 additions and 14 deletions

219
README.md
View File

@ -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
View 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!

View File

@ -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!