Lua’s study notes (1)

Time:2020-10-26

1 Introduction

Implemented by clean C. It needs to be called by the host program, and can be injected into the C function.

2 grammar

The grammar rules based on BNF are adopted.

2.1 grammar conventions

Lua is case sensitive.

2.1.1 reserved keywords

The keywords not available in C language are:

and elseif function
in nil local not or
repeat then until

standard:Global variables begin with an underline.

2.1.2 operators

Operators not available in C language:

^ 
~= 
//-- round down

Operators not in Lua:

+=
-=

2.1.3 string definition

Use escape character: Express ambiguous characters by escape character

Character representation

A -- represents the character a
 -- stands for character a
9 -- represents the numeric character 1

Other escape characters

\N -- represents the string
\N -- stands for line break

be carefulNumeric characters must be three digits. Other characters cannot exceed three digits.

Using long brackets: all contents in long brackets are treated as normal characters.

[[]] -- 0 level long bracket
[= = = [] = = =] -- 2 levels of long brackets

2.2 values and types

Lua is a dynamic language. Variables have no type, only values. The value itself carries type information.

Lua has eight basic data types:nil, boolean, number, string, function, userdata, thread, table

onlynilandfalseThe result is that the condition is false and the others are true.

userdataType variables are used to hold C data. Lua can only use this kind of data, but can not create or modify it to ensure that the host program can fully grasp the data.

threadUsed to implement coroutine.

tableUsed to implement associative arrays.tableAny type of data is allowed to be indexed, and any type is allowed to do sotableThe values in the
Any typeNil is not included).tableIs the only data structure in Lua.
Because a function is also a value, sotableFunctions can be stored in.

function, userdata, thread, table Values of these types are objects。 These types of variables areJust save a reference to the variableIn addition, it will not copy any properties during assignment, parameter passing, function return, etc.

Library functiontype()Returns the type description of a variable.

2.2.1 forced conversion

Provided by LuanumberAndcharacter stringAutomatic conversion between.
You can use the format function to control the conversion of numbers to strings.

2.3 variables

There are three types of variables:Global variables, local variables, fields in a table

Out of functionThe variable of is global by default, unless it is declared with local display.In functionThe parameters of variables and functions are local variables by default.

The scope of a local variable is from the declaration position to the end of the statement block (or until the declaration of the next local variable with the same name).

The default value of variables is nil.

A = 5 -- global variable
Local B = 5 -- local variable

function joke()
    C = 5 -- local variable
    Local d = 6 -- local variable
end

print(c,d)      --> nil nil

do 
    Local a = 6 -- local variable
    B = 6 -- global variable
    print(a,b); --> 6 6
end

print(a,b)      --> 5 6

Convenient marking,-->Represents the result of the previous expression.

2.3.1 index

Use square brackets for the index of table[]。 Lua uses grammar sugar to provide.Operation.

t[i]
t. I -- a simplified writing method when the index is a string type
gettable_ Event (T, I) -- index access is essentially a function call like this

2.3.2 environment table

All global variables are placed in a single environment table named_env。 For a global variableaThat is_env.a_env_Just for the sake of illustration).

Each function as a variable holds a reference to an environment table, which contains all the variables that the function can call.
The child function inherits the environment table from the parent function.
You can use the functiongetfenv / setfenvTo read and write the environment table.

2.4 statement

Support assignment, control structure, function call, and variable declaration.

Empty statement segments are not allowed, therefore;;It’s illegal.

2.4.1 sentence groups

chunck ::= {stat[';']}

([';']It should be after the statement group;Is optional. )

2.4.2 statement blocks

block ::= chunck
stat ::= do block end

It can be used to control the scope of local variables.

2.4.3 assignment

Lua supports multiple assignments.

In multiple assignments, the value of the expression on the right is assigned to the left value in order. If the right value is insufficient, nil will be supplemented, and the surplus right value will be discarded.

b = 1
a,b = 4 -- a = 4,b = nil 

+++

Lua will calculate all the expressions on the right at one time and then assign the value.

i = 5
i,a[i] = i+1, 7 -- i = 6 ,a[5] = 7

In particular, there are

x. Y = y, X -- exchange the values of X, y

+++

The meaning of assignment operations to global variables and table fields can be changed in the meta table.

2.4.4 control structure

Conditional statement

if [exp]
    [block]
elseif [exp]
    [block]
else
    [block]
end

Loop statement

while [exp]
    [block]
end

+++

repeat
    [block]
until [exp]

Attention, becauserepeatStatement tountilIt’s not over yet, so inuntilYou can use theblockLocal variables defined in.

For example:

a = 1
c = 5
repeat
    b = a + c
    c = c * 2
until b > 20
print(c)            -->     40

+++

breakandreturn

breakandreturnIt can only be written in the last sentence of the statement block. If it really needs to be written in the middle of the statement block, it will be surrounded by two keywordsdo endStatement block.

do break end

2.4.5 Forloop

forThere are many usages of circulation, which can be mentioned separately.

forThe expression in is evaluated once before the start of the loop and is not updated during the loop.

Digital form

for [Name] = [exp],[exp],[exp] do [block] end

The three Exps representInitial value, end value, step。 The value of exp needs to be a number.
The third exp is 1 by default and can be omitted.

a = 0

for i = 1,6,2 do
    a = a + i
end

Equivalent to

int a = 0;
For (int i = 1; I < = 6; I + = 2) {// get the equal sign, if the step is negative, then I > = 6
    a += i;
}

Iterator form

When a table is output in the form of iterator, if there are functions in the table, the order and number of outputs are uncertain (the result of the author’s test, the specific reason is unknown).

The essence of iterator form for loop

--Return iterator, state table, iterator initial value in turn
function mypairs(t)

    function iterator(t,i)
        i = i + 1
        I = t [i] and I -- if t [i] = = nil, then I = nil; otherwise I = I
        return i,t[i]
    end

    return iterator,t,0

end

--A watch
t = {[1]="1",[2]="2"}

--Equivalent form of iterative form for statement
do
local f, s, var = mypairs(t)
    while true do
        local var1, var2 = f(s, var)
        var = var1
        if var == nil then break end

        --Statement added in for loop
        print(var1,var2)

    end
end

--Iterative form for statement
for var1,var2 in mypairs(t) do
    print(var1,var2)
end

--> 1   1
--> 2   2
--> 1   1
--> 2   2
Array form
ary = {[1]=1,[2]=2,[5]=5}
for i,v in ipairs(ary) do
    print(v)                    --> 1 2
end

It starts at 1 and ends at the end of the numeric subscript or nil.

Table traversal
table = {[1]=1,[2]=2,[5]=5}
for k,v in pairs(table) do
    print(v)                    --> 1 2 5
end

Traverse the key value pairs of the entire table.

For more information about iterators, please refer toLua iterator and generic for

2.5 expression

2.5.1 mathematical operation operator

%Operator

In Lua%Although operators and operators in C language are the meaning of modulus, the mode of taking module is different.
In C language, modulus operation is to add the sign of the first operands after taking the absolute value of two operands.
In Lua, it is simply the remainder after rounding down the quotient relative negative infinity.

+++

In C,

a1 = abs(a);
b1 = abs(b);
c = a1 % b1 = a1 - floor(a1/b1)*b1;

a % b = (a >= 0) ? c : -c;

In Lua,

a % b == a - math.floor(a/b)*b

Lua operates directly according to the definition of modulus. C does a little bit of processing for modular operation.

+++

give an example:

In C

int a = 5 % 6;
int b = 5 % -6;
int c = -5 % 6;
int d = -5 % -6;

printf("a,b,c,d");--5,5,-5,-5

In Lua

a = 5 % 6
b = 5 % -6
c = -5 % 6
d = -5 % -6

x = {a,b,c,d}

for i,v in ipairs(x) do
    print(i,v)
end


--> 5
--> -1
--> 1
--> -5

It can be seen that only when the operands are the same, the two languages have the same modulus results. When the sign is different, the sign and the value of the modulus result are not equal.

The modular operation in Lua is summarized as follows: a% B, if a and B are the same sign, the result is the modulus of absolute value of a and B; if the sign is different, the result is the difference between the absolute value of B and the modulus of absolute value. The sign of the value after taking module is the same as that of B.

2.5.2 comparison operator

The result of the comparison operation isbooleanType, nottrueNamelyfalse

The supported operators are:

< <= ~= == > >=

I won’t support it!Operator.

+++

about==Operation. The type of the two operands is compared first. If they are inconsistent, the result is false. There is no automatic conversion between the value and the string.

When comparing whether two objects are equal, only when they point to the same memory area, it is determined astrue。·

a = 123
b = 233
c = "123"
d = "123"
e = {1,2,3}
f = e
g = {1,2,3}

print(a == b)       --> false
Print (a = = C) -- > false -- Compare numbers and strings as different types
print(c == d)       --> true       
Print (E = = f) -- > true -- the reference points to the same object
Print (E = = g) -- > false -- although the contents are the same, they are different objects
Print (false = = Nil) - > false -- false is Boolean, nil is nil type

Convenient marking,-->Represents the result of the previous expression.

+++

userdataAndtableCan be compared by meta methodeqMake changes.

In size comparison, the comparison of numbers and strings is consistent with C language. If it’s a different type of value, Lua tries to call the meta methodltandle

2.5.3 logical operators

and,or,not

Only think thatfalseAndnilFalse.

not

Reverse operationnotThe result isbooleanType. (andandorThe result is not necessarilyboolean)

B = not a -- A is nil, B is true
C = not not not a -- C is false

and

a and b, ifaFalse, returna, ifaTrue, returnb

Attention, whyaReturn when you’re fakeaWhat about it? What’s the point? that is becauseaIt could befalseperhapsnilThe two values are false, but they are different.

or

a or b, ifaFalse, returnb, ifaTrue, returna。 Andandcontrary.

+++

Tips:When logical operators are used to derive abooleanIt is unnecessary to consider who is returned after the logical operation, because the operation result of the logical operator conforms to the original logical meaning.

give an example

If (not (a > min and a < max)) then
    error() 
end

+++

other

andAndorFollowing the short-circuit principle, the second operands are evaluated only when needed.

example

a = 5
X = a or jjjj () -- although the latter function is not defined, it will not report an error because it will not be executed.


print(a)        -->5
print(x)        -->5

From the example above, we should be alert to logical operations, which may introduce errors that are not expected in time.

2.5.4 connectors

..
Concatenates two strings (or numbers) into a new string. For other types, call the meta methodconcat

2.5.5 take length operator

#

For strings, the length is the number of characters in the string.

For a table, the length of the table is determined by finding the subscript n satisfying that t [n] is not nil and T [n + 1] is nil.

~~What about other types? ~ ~

example

--String length
print(#"abc
--String length
print(#"abc\0")                         --> 4
--Watch length
print(#{[1]=1,[2]=2,[3]=3,x=5,y=6})     --> 3
print(#{[1]=1,[2]=nil,[3]=3,x=5,y=6})   --> 1
") --> 4 --Watch length print(#{[1]=1,[2]=2,[3]=3,x=5,y=6}) --> 3 print(#{[1]=1,[2]=nil,[3]=3,x=5,y=6}) --> 1

2.5.6 priority

From low to high:

or
and
 <     >     <=    >=    ~=    ==
 ..
 +     -
 *     /     %
 not   #     - (unary)
 ^

Power operation > monocular operation > four rule operation > connector > comparison operator > and > or

2.5.7 table structure

BNF definition of table construction

tableconstructor ::= `{´ [fieldlist] `}´
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp
fieldsep ::= `,´ | `;´

give an example:

a = {}
b = {["price"] = 5; cost = 4; 2+5}
C = {[1] = 2 + 5, [2] = 2, 8, price = ABC ", [" cost "] = 4} -- tables constructed by B and C are equivalent


print(b["price"])   --> 5
print(b.cost)       --> 4
Print (B [1]) - > 7 -- if the key value is not given, the subscript is allocated in order, and the subscript starts from 1

print(c["price"])   --> abc
print(c.cost)       --> 4
print(c[1])         --> 8       
print(c[2])         --> 2

be careful:

  • If the key value is not given, the subscript is allocated in order, and the subscript starts from 1
  • If there are the same keys in the table, the value at the bottom is used as the value for the key

The existence of these two above makes C in the above example1The output value of is 8.

+++

If there are the same keys in the table, the value at the bottom is used as the value for the key.

A = {[1] = 5, [1] = 6} -- then a [1] = 6

+++

If the last field of the table is in the form of an expression and is a function, all the return values of that function are added to the table.

a = 1
function order()
    a = a + 1
    return 1,2,3,4
end

b = {order(); a; order(); }

c = {order(); a; (order());}

print(b[1])                     --> 1       
Print (B [2]) - > 2 -- the values in the table are not assigned after all expressions are evaluated at once
print(b[3])                     --> 1       
Print (B [4]) - > 2 -- multi return value function in the form of expression

Print (ා b) -- > 6 -- the length of the table is 6                 
Print (# C) -- > 3 -- the length of the table after adding brackets is 3

2.5.8 function definition

A function is an expression whose value is an object of type function. The function is instantiated each time it is executed.

There are three forms of implementing a function in Lua.

f = function() [block] end
local f; f = function() [block] end
a.f = function() [block] end

Lua provides syntax sugar to handle these three function definitions separately.

function f() [block] end
local function f() [block] end
function a.f() [block] end

+++

abovelocalThe definition of function is notlocal f = function() [block] endTo avoid the following errors:

local f = function()
    print("local fun")
    if i==0 then 
        F () -- compilation error: attempt to call global 'f' (a nil value)
        i = i + 1
    end
end

The parameters of the function

Formal parameters are initialized as local variables through arguments.

Add at the end of the parameter list...Indicates that the function can accept indefinite length parameters. If the tail is not added, the parameter list length of the function is fixed.

f(a,b)
g(a,b,...)
H (a,..., b) -- compilation error
f(1)                    --> a = 1, b = nil
f(1,2)                  --> a = 1, b = 2
f(1,2,3)                --> a = 1, b = 2

g(1,2)                  --> a = 1, b = 2, (nothing)
g(1,2,3)                --> a = 1, b = 2, (3)
g(1,f(4,5),3)           --> a = 1, b = 4, (3)
g(1,f(4,5))             --> a = 1, b = 4, (5)

+++

There is also a way to define a function whose formal parameter is self

a.f = function (self, params) [block] end

The grammatical sugar forms are as follows:

function a:f(params) [block] end

Examples of use:

A = {name = "Tangyi Kejun"}
function a:f()
    print(self.name)
end
a: If you use a.f(), then self.name  The error attempt to index local 'self' will be reported; in this case, it should be written as a.f (a)

:The function of function definition and call can be less than oneselfParameter. This form is rightmethodSimulation of

2.5.9 function call

The BNF syntax of function calls in Lua is as follows:

functioncall ::= prefixexp args

If the value of prefixexp is of type function, the function is called with the given parameters. Otherwise, the meta method “call” of prefixexp is called. The first parameter of call is the value of prefixexp, followed by the args parameter list (see2.8 meta table)。

The function call depends on whether it is passed in or notselfThe parameters are divided into.Calling and:Call.
Function calls can be divided intoParameter list call, table call, string call

[to be improved]

2.5.10 function closure

If a function accesses its external variables, it is a closure.

Because the variables inside the function are local variables, it can not be accessed by the outside world. In this case, if the outside world wants to change the value of the local variable, the closure can be used to achieve this purpose.
The specific implementation process is roughly like this: there is a sub function inside the function that can change the local variable. If the function returns this sub function, the external world can operate the local variable by using this sub function.

example:Using closure to change local variables

--Implement an iterator

function begin(i)
    local cnt = i

    Return function() -- this is an anonymous function that implements the auto increment function; it is also a closure because it accesses the external variable CNT
        cnt = cnt + 1
        return cnt
    end
end


Iterator = begin (2) -- set the initial value of iterator to 2, and return an iterator function

Print (iterator ()) -- performs iteration
print(iterator())

Tips:For more instructions on closures, please refer toHow does JavaScript closure work

Visual rules

The scope of the variable, see2.3 variablespart.

2.7 error handling

[to be added]

2.8 meta table

We can use operators to operate on Lua’s value, such as adding, subtracting, multiplying and dividing the value of numerical type, as well as string connection, length operation, etc2.5 expressionMany similar operations are described in this section. The meta table is where these operations are defined.

The meta table is essentially a regular Lua table. The key in the meta table is used to specify the operation, which is called the “event name”; the value associated with the key in the meta table is called the “meta method”, which defines the behavior of the operation.

2.8.1 event name and meta method

Only the meta table corresponding to the table type value can be defined by the user. Meta tables corresponding to other types of values can only be modified through the debug library.

Event names in the meta table are underlined with two lines__As a prefix, the meta table supports the following event names:

Wei Index -- 'table [key]' is used to access the fields in the table
Wei Newindex -- 'table [key] = value', assignment operation, adding or modifying fields in the table
Wei Call -- 'func (args) ", function call, see [2.5.9 function call] (ා2-5-9)

--Mathematical operation operator
__add       -- '+'
__sub       -- '-'
__mul       -- '*'
__div       -- '/'
__mod       -- '%'
__pow       -- '^'
__unm       -- '-'

--Join operator
__concat    -- '..'

--Length operator
__len       -- '#'

--Comparison operator
__eq        -- '=='
Wei LT -- '<' -- a > b is equivalent to B < a
Wei Le -- '< =' -- a > = B is equivalent to B < = a

There are other events, such as__tostringand__gcEtc.

The following is a detailed introduction.

2.8.2 meta tables and values

Each value can have a meta table. For the user data and table types, each value can have a separate meta table, or several values can share a meta table. For other types, values of one type share a meta table. For example, values of all numeric types share a meta table. Except for string type, other types of values have no meta table by default.

Use the getmetatable function to get a meta table of any value.getmetatable (object)
Use the setmetatable function to set theTable typeMeta table of values.setmetatable (table, metatable)

example

Only values of type string have a metatable by default:

a = "5"
b = 5
c = {5}
print(getmetatable(a))      --> table: 0x7fe221e06890
print(getmetatable(b))      --> nil
print(getmetatable(c))      --> nil

2.8.3 details of the incident

Remind Lua to use it in advancerawThe prefix function is used to operate the meta method to avoid the circular call of the meta method.

For example, Lua gets the meta method in obj as follows:

rawget(getmetatable(obj)or{}, "__"..event_name)

Meta method index

Index is the most commonly used event in the meta table for subscript access to values–table[key]

The value of the event index can be a function or a table. When a table is used for assignment, the meta method may trigger another call to the meta method. For details, see the pseudo code description below.
When a user accesses a table through a key value, if the value corresponding to the key is not found, this event is called in the corresponding meta table. If the index uses a table for assignment, it finds the corresponding value of the passed in key in the table; if the index uses a function for assignment, the function is called and the table and key are passed in.

Lua’s processing of subscript operation is represented by pseudo code as follows:

function gettable_event (table, key)
    --H represents the value of index in the meta table
    local h     
    if type(table) == "table" then

        --Successful visit
        local v = rawget(table, key)
        if v ~= nil then return v end

        --If the access is unsuccessful, try to call the index of meta table
        h = metatable(table).__index

        --Nil returned when meta table does not exist
        if h == nil then return nil end
    else

        --Instead of accessing the table, try the meta table directly
        h = metatable(table).__index

        --Unable to process caused an error
        if h == nil then
            error(···);
        end
    end

    --Handle according to the value type of index
    if type(h) == "function" then
        Return H (table, key) -- call processor
    else 
        Return h [key] -- or repeat the above operation
    end
end

example:

Use table assignment:

t = {[1] = "cat",[2] = "dog"}
print(t[3])             --> nil
setmetatable(t, {__index = {[3] = "pig", [4] = "cow", [5] = "duck"}})
print(t[3])             --> pig

Use function assignment:

t = {[1] = "cat",[2] = "dog"}
print(t[3])             --> nil
setmetatable(t, {__index = function (table,key)
    key = key % 2 + 1
    return table[key]
end})
print(t[3])             --> dog

Metamethod newindex

Newindex is used for assignment operations–talbe[key] = value

The value of the event newindex can be a function or a table. When a table is used for assignment, the meta method may trigger another call to the meta method. For details, see the pseudo code description below.

The metamethod of newindex is called when the operation type is not a table or the passed in key does not exist in the table. If newindex is associated with a value other than a function type, the value is assigned again. Instead, call the function directly.

~~Not too clear: once the “newindex” metamethod is available, Lua does not do the initial assignment. (if necessary, rawset can be called inside the meta method to do the assignment.) ~ ~

The pseudo code of lua is as follows:

function settable_event (table, key, value)
    local h
    if type(table) == "table" then

        --Modify the value corresponding to the key in the table
        local v = rawget(table, key)
        if v ~= nil then rawset(table, key, value); return end

        -- 
        h = metatable(table).__newindex

        --If there is no meta table, add a field directly
        if h == nil then rawset(table, key, value); return end
    else
        h = metatable(table).__newindex
        if h == nil then
            error(···);
        end
    end

    if type(h) == "function" then
        Return H (table, key, value) -- call processor
    else 


        H [key] = value -- or repeat the above operation
    end
end

example:

The meta method is a table type:

t = {}
mt = {}

setmetatable(t, {__newindex = mt})
t.a = 5
print(t.a)      --> nil
print(mt.a)     --> 5

The new domain is added to the table MT by calling the newindex meta method twice.

+++

The meta method is a function

--Different assignment methods are used for different types of keys
t = {}
setmetatable(t, {__newindex = function (table,key,value)
    if type(key) == "number" then
        rawset(table, key, value*value)
    else
        rawset(table, key, value)
    end
end})
t.name = "product"
t[1] = 5
print(t.name)       --> product
print(t[1])         --> 25

Meta method call

The call event is used for function calls–function(args)

Pseudo code of lua when calling a function:

function function_event (func, ...)

  if type(func) == "function" then
      Return func (...) -- Native call
  else
      --If it is not a function type, the call meta method is used to make the function call
      local h = metatable(func).__call

      if h then
        return h(func, ...)
      else
        error(···)
      end
  end
end

example:

Since users can only bind custom meta tables for the values of table type, we can make function calls on the table instead of using other types of values as functions.

--Record the data to the table and return the data processing results
t = {}

setmetatable(t, {__call = function (t,a,b,factor)
  t.a = 1;t.b = 2;t.factor = factor
  return (a + b)*factor
end})

print(t(1,2,0.1))       --> 0.3

print(t.a)              --> 1
print(t.b)              --> 2
print(t.factor)         --> 0.1

Operation operator correlation element method

The operation operator correlation element method is naturally used to define operations.

Taking add as an example, Lua’s pseudo code when implementing add operation is as follows:

function add_event (op1, op2)
  --When the parameter can be converted to a number, ToNumber returns a number, otherwise nil is returned
  local o1, o2 = tonumber(op1), tonumber(op2)
  If O1 and O2 then -- are both operands numbers?
    Return O1 + O2 -- here '+' is the native 'Add'
  Else -- when at least one of the operands is not a number
    local h = getbinhandler(op1, op2, "__ Add ") -- this function is described below
    if h then
      --The processor is called with two operands
      return h(op1, op2)
    Else -- no processor: default behavior
      error(···)
    end
  end
end

The getbinhandler function in the code defines how Lua chooses a processor for binary operations. In this function, first, Lua tries the first operand. If the type of the operands does not define a processor for the operation, then Lua tries the second.

 function getbinhandler (op1, op2, event)
   return metatable(op1)[event] or metatable(op2)[event]
 end

+++

For unary operators, such as negative, Lua’s PN code when implementing the UN m operation is as follows:

function unm_event (op)
  local o = tonumber(op)
  If o then -- is the operand a number?
    Return - O -- here '-' is a native 'UN M'
  Else -- the operands are not numbers.
    --Try to get the processor from the operands
    local h = metatable(op).__unm
    if h then
      --Calling the processor with the operands as parameters
      return h(op)
    Else -- no processor: default behavior
      error(···)
    end
  end
end

example:

Examples of addition:

t = {}
setmetatable(t, {__add = function (a,b)
  if type(a) == "number" then
      return b.num + a
  elseif type(b) == "number" then
      return a.num + b
  else
      return a.num + b.num
  end
end})

t.num = 5

print(t + 3)  --> 8

Examples of negative:

t = {}
setmetatable(t, {__unm = function (a)
  return -a.num
end})

t.num = 5

print(-t)  --> -5

Meta methods for other events

For a join operation, the meta method is called when there is a type other than a numeric or string in the operands.

For the fetch operation, if the operands are not of string type or table type, try to use meta method (this leads to the lack of custom fetch, which seems to be improved in later versions).

For the three comparison operations, the meta method can only be used when the two operands are of the same type and are associated with the same meta table.

For EQ (equal to) comparison, if the type of the operands does not have a native equal comparison, the meta method is called.

For the comparison operations of LT (less than) and le (less than or equal to), if the two operands are both numeric values or strings, they are compared directly. Otherwise, the meta method is used.

For the Le operation, Lua tries “lt” if the meta method “Le” is not provided, which assumes that a < = B is equivalent to not (b < a).

For the toString operation, the meta method defines the string representation of the value.

example:

Take length operation:

t = {1,2,3,"one","two","three"}
setmetatable(t, {__len = function (t)
  local cnt = 0
  for k,v in pairs(t) do
    if type(v) == "number" then 
      cnt = cnt + 1
      print(k,v)
    end
  end
  return cnt
end})

--The result was 6, not the expected 3
print(#t)   --> 6

Equal to comparison operation:

t = {name="number",1,2,3}
t2 = {name = "number",4,5,6}
mt = {__eq = function (a,b)
    return a.name == b.name
end}
Set metatable (T, MT) -- you must associate the same meta table to compare
setmetatable(t2,mt)

print(t==t2)   --> true

ToString operation:

t = {num = "a table"}
print(t)              --> table: 0x7f8e83c0a820

mt = {__tostring = function(t)
  return t.num
end}
setmetatable(t, mt)

print(tostring(t))    --> a table
print(t)              --> a table

2.9 environmental table

typethreadfunctionanduserdataIn addition to being associated with a meta table, an object of can also be associated with an environment table.

The environment table associated with the thread is called the global environment.
The global environment is the default environment for child threads and child functions.
The global environment can be called directly by C.

The environment table associated with Lua function takes over all access to global variables by the function. And as the default environment for child functions.

The environment associated with a C function can be called directly by C.

Associated inuserdataThere is no practical use for the environment on, just for the convenience of programmers to associate a table withuserdataGo ahead.

2.10 garbage collection

2.10.1 meta method of garbage collection

[to be added]

2.10.2 weak table

A weak table is a table that contains a weak reference.

There are three ways of weak reference for weak tables.Key weak reference, value weak reference, key and value weak reference

You can use the__modeField to set whether a table has a weak reference and how to use it.

a = {}
b = { __ Mode = "K"} -- add K to the quotation marks to indicate weak key reference, V to value weak reference, and kV to all weak references.
Setmetable (a, b) -- B is the meta table of a, which cannot be changed after binding__ The value of mode.

The garbage collection mechanism recycles the weak references. However, no matter what kind of weak reference, the recycling mechanism will remove the entire key value pair from the weak table.

3 program interface (API)

This section describes Lua’s C API, that is, C functions used to communicate with Lua. All functions and constants are defined inlua.hIn the header file.

Some C functions are implemented in macro. ~ ~Why? :Because all macros use their arguments only once (except for the first parameter, that isLua state machine)So you don’t have to worry about the side effects of macro expansion. ~ ~

By default, Lua does not check the validity and robustness of a function when making a function call. If you want to check, use theluaconf.hMediumluai_apicheck()Function on.

3.1 stack

Lua uses a virtual stack to pass parameters when calling C API. All elements in the stack are of lua type (for examplebooleantablenilEtc.).

Lua creates a new virtual stack when calling C functions, instead of using the old stack or other stacks. At the same time, in the C function, when calling Lua API, only the elements in the stack corresponding to the current call can be used, and the elements of other stack can not be accessed.
The virtual stack contains all the parameters required by the C function, and the return value of the function is also placed in the stack.

The so-called stack concept here is not a stack in strict sense, and the elements in the stack can be accessed through subscripts. 1 is the bottom of the stack, – 1 is the top of the stack, and for example, 3 is the third element starting from the bottom of the stack.

3.2 stack size

Since Lua’s C API does not do validity and robustness (robustness) testing by default, developers are responsible for ensuring robustness. In particular, do not let the stack overflow. Lua only guarantees that the stack size is greater thanLUA_MINSTACK(usually 20). Developers can uselua_checkstackFunction to manually set the stack size.

3.3 pseudo index

In addition to accessing Lua elements of the function stack with an index, C code can also use thePseudo indexTo access Lua elements outside the stack, such as thread environment, registry, function environment, and C function’supvalue(upper value). Pseudo indexes can be disabled by special declaration.

Thread environment is placed in pseudo indexLUA_GLOBALSINDEXThe environment of the function is placed in the pseudo indexLUA_ENVIRONINDEXDepartment.

The way to access the environment is consistent with the way to access the table. For example, to access the value of a global variable, you can use:

lua_getfield(L,LUA_GLOBALSINDEX,varname)

3.4 C closure

When we associate the created function with some values, we get a closure. Those associated values are calledupvalue(upper value).

The upper value of the function is placed at a specific pseudo indexlua_upvalueindexGets the pseudo index of the value on. for examplelua_upvalueindex(3)Indicates that the pseudo index corresponding to the third association value (in order of association) is obtained.

3.5 registration form

Lua provides a registry. C code can be used to store Lua values that you want to store. Pseudo index for registryLUA_REGISTRYINDEXlocation.

In order to avoid naming conflicts, the string containing the library name is generally used as the key name. ~ ~What’s that? :Or you can take an address in your own C code and make the key in the form of light UserData. ~ ~

The integer key in the registry has a specific purpose (used to implement the reference system of the supplementary Library), and is not recommended for other purposes.

Error handling in 3.6 C

[to be added]

3.7 functions and types

This section describes the functions and types in the C API.

For the rest, seeLua’s learning notes (2)


Reference link

Brief introduction to BNF paradigm(brief introduction to BNF)
Lua introduction series – jelly(a comprehensive introduction to Lua)
Lua quick start(introduce some of the most important concepts in Lua for C / C + + programmers)
Lua 5.1 Chinese Manual(comprehensive lua5.1 Chinese manual)
Lua 5.3 Chinese Manual(it took Yun Fenghua 6 days to write it. My God, I think it depends on the rhythm of 6 days.)
Lua iterator and generic for(introduce the detailed principle and use of lua iterator)
How do JavaScript closures work?——StackOverflow(introduces the concept of closure in JavaScript in detail)
Lua pattern matching(refer to the%bUse of)
LuaSocket(official Manual of luasocket)
Lua LoadFile usage, compared with other functions(this article is quoted in the introduction of LoadFile)
Lua’s metatable(the description of meta table is organized and easy to understand. This paper refers to this article for meta table part)
Setting function environment — setfenv(explains how to easily set up the environment for a function and why it should be set that way)
Setfenv in lua5.1 uses(this paper introduces an application of the environment setting in practice)