⬆️ ⬇️

Language Lua and Corona SDK (2/3 part)

image



This is the second of the three parts of the article on the basic concepts of the Lua language for the Corona SDK (if you have not read the first part I advise you to start with it), in this part we will look at all the data types in the language. You will learn how to initialize variables of all types, use their values, and convert one type to another. This article is extremely important in the matter of learning the language and I tried to add a large number of valuable tips that will allow you to avoid many mistakes when you write your games.



Types of data and their conversion



Lua has 8 data types. Before considering the types I will focus on the standard function of the lua language - type. This function returns a string with the name of the data type of the specified variable or data. An example of using the type function:



n = nil st = '' pi = 3.14 func = function()end t = {} b = true co = coroutine.create(function ()end) print(type(n), type(st), type(pi), type(func), type(t), type(b), type(co)) --: nil string number function table boolean thread 


Next, consider the types of the language Lua.

')

Nil type



This data type defaults to any variable that has no value assigned. All nil variables are nil. You can assign this type to a variable in two ways:



 local B = nil--   local A--    -- -        nil 


It is worth noting that if a variable has not been initialized in the current scope, its type and value will be nil. A variable having a nil type can be compared in the order of comparing a logical variable having a value of false through the logical not operation, but in reality these types are not similar, I will give an example:



 n = nil b = false if not n then--true print(1) end if not b then--true print(2) end if b == n then--false print(3) end -->> 1 -->> 2 


Type boolean



The type boolean is also called a boolean or boolean type, since it is used to implement comparison operations. As already mentioned above, boolean has only 2 possible values ​​of false and true ( false and true ). Since all the comparison operations return exactly these values ​​- the variables of this type can be initialized by assigning the values ​​of the comparative operation to them, it can also be initialized by directly assigning the values. Variables of type boolean can be compared only with equality and inequality operations, as well as directly as a comparison condition in if / elseif



 --    b1 = false b2 = true --   b3 = b1 ~= b2--true b4 = b1 == b2--false if b1 == b3 then--true print(true) end if b3 then print(true) end 


Type number



An extended numerical type, its full description is significantly beyond the scope of this text, so inquisitive users can follow the link and become familiar with the specification in detail. I can only say that both negative and positive numbers, both integers and floating point, can accommodate this type, at certain levels of positive and negative digit capacity, an automatic transition to the exponential form of numbers takes place, the limits of bit capacity depend on the device’s processor capacity, but currently Corona SDK has support for Android 4.0.3+, which most likely means that all available devices will be 64 bit. To initialize variables of the number type, it is sufficient either to explicitly assign a value in one of the available formats, either assign the result of a calculation to a variable, or equate it with another variable of this type. I note that any variable of type number in operations of logical comparison returns true, even 0 (and even -1), this should be taken into account by fans of the language c ++ ( and similar ) where 0 is the equivalent of false. I will give an example of operations with the number type:



 local a,b = 2,3--  local c = a + b--   --   d = 12e5 -- 1 200 000 e = 2e-3 -- 0.002 --   f = 0x234 -- 564 --  j = 1.23 k = .55 -- 0.55 -    1       


Number variables can be performed using a series of numerical operations, the main of which are shown in the example:



 a = b + c --  a = b - c -- a = b * c --  a = b / c --  a = b % c --    a = b ^ c -- b   c 


Type string



The String type is quite well developed in Lua and, complete with variables, this type comes with many amenities. How to create string variables:



 local st1 = 'qwert'--  st2 = st1--   st3 = st1 .. st2--    


As you noticed from the example, the concatenation ( concatenation ) of strings is performed by two points, and the concatenation process itself can be used as one of the ways to convert a number into a string, I will give an example:



 i = 10--number st = '11'--string konc1 = 1 .. st --  konc2 = 100..''--       string print(konc1, konc2, type(konc1) , type(konc2 )-->>111 100 string string 


As you can see, the translation from number to string is quite simple. I want to note that if you use a string concatenation, it is best to put a space between the clutch operator and operands, but this is not always necessary, but it’s best to get used to it because, firstly, it’s so prettier and clearer, and secondly if one of the operands - a number ( not a variable equal to a number, but a number ), then if you do not put a space, the error " malformed number near " will occur. There are more traditional approaches to converting, I will give an example of a transfer to both sides:



 i1 = 1 s1 = '11' i2 = tonumber(s1)-- string -> number s2 = tostring(i1)--  number -> string 


I would also like to add that the implicit conversion of a string into a number also exists, but I strongly advise you not to do this — this is completely ugly and will almost certainly lead to a complex error:



 --      st = '10' i = 10 + st print(i, type(i))-->> 20 number 


When initializing variables of the string type, it is not uncommon for complex moments to arise, which I will briefly describe and present ways to solve them:





As I wrote above, the string contains a lot of useful amenities, they are implemented using the functions that we consider below.



string.len (s) / s: len ()



The function allows you to determine the length of the string. This, like most of the other functions from the string library, can be used in two ways, but there are features, below is an example of use:



 --  string.len(s) local st = 'Hello World!' local len_st = string.len(st) print(len_st)-->>12 --  s:len() local le_st = st:len() print(len_st)-->>12 --    print(string.len('Examlpe string'))-->>14 --   -    --      print('Examlpe string':len())-->> Error: ')' expected near ':' 


As you may have noticed, there is an incorrect way to use the function, the comments explain the essence of the error. The rule of using functions common to all other functions of the library, so in the future I will not stop on this in detail.



string.byte (s [, i [, j]]) / s: byte ([i [, j]])



The function returns the character codes of the string from i-th to j-th. Parameters i and j are not required and if you do not specify j, only the code of the i-th element will be returned, if you do not specify i, but specify j, character codes from the first to the jth will be returned, unless you specify i and j will be returned code of the first character in the string. I will give an example of using the function:



 local s = 'Example' print(s:byte())--  >> 69 print(string.byte(s, 3))--  >> 97 print(string.byte(s,nil, 4))--   4- >> 69 120 97 109 print(s:byte(nil, s:len()))--  >> 69 120 97 109 112 108 101 


string.char (i1, i2, ...)



One or more parameters with character numbers are passed to the function, and a string equal to all the characters transferred is returned. This function has the opposite purpose with respect to the string.char () function. Examples of using:



 print(string.char(65)) -->> A print(string.char(72,101,108,108,111)) -->> Hello local s = 'Example' print(string.char(s:byte(1,s:len())))-- s:byte   --- st        >> Example 


string.find (s, pattern [, index [, no_regular]])

s: find (pattern [, index [, no_regular]])



Using the find function, you can find in the string s the position of the pattern pattern or nil if not found. Pattern pattern can be either a string or a regular expression ( you will learn more about regular expressions in a separate chapter ). Consider the simplest version of the use of find. We next turn to the features of the optional parameters:



 local s = "Hello Lua!" print(string.find(s,"Lua"))--      --  Lua   s >> 7 9 print(s:find("%sL"))--    " -- L       " >> 6 7 


The index parameter defaults to 1 and this means that the position of the first found entry is returned if you search from the beginning, if you set index to 3, then the third entry in the string will be returned from the beginning, but if -3, then the 3rd entry with end of line. The parameter no_regular is logical, i.e. true / false (true / false), the default parameter is false, if set to true, then the pattern parameter will always be perceived as a regular string, even if you enter a regular expression into it. I will give an example of the expanded use of find:



 s = 'La La La La %sLa La' print(s:find('La', 2)) --    >> 4 5 print(s:find('La', -2)) --    >> 18 19 print(s:find('%sLa', 1, true)) -->>  ,    >> 13 16 


string.format (s, e1, e2, ...)

s: format (e1, e2, ...)



The string.format function creates a formatted string with a set of arguments. At first glance, this function may seem complicated in understanding, but in fact it can greatly simplify many constructions when outputting final information, as well as very conveniently used for other indirect transformations, for example, from number to a string of hexadecimal code. I will give the simplest example:



 local sum1,sum2 = 100,200--   print(string.format('Value1: %d, Value2: %d', sum1,sum2))-->> Value1: 100, Value2: 200 


As you can see, first comes the format of the line, which contains arguments showing how to use the parameters following this parameter. There are 11 ( c, d, E, e, f, g, i, o, u, X, x ) arguments for controlling numeric values ​​and 2 ( s, q ) arguments for managing strings. Then I’ll briefly dwell on each argument and then give examples of usage:





 print(string.format('Number: %d, Signed: %i, Unsigned: %u', 100,-100,-200)) -->> Number: 100, Signed: -100, Unsigned: 4294967096 print(string.format("%c%c%c%c%c%c%c", 69,120,97,109,112,108,101)) -->> Example print(string.format("%e, %E", math.pi,math.pi))-->> 3.141593e+000, 3.141593E+000 print(string.format("%f, %g", math.pi,math.pi))-->> 3.141593, 3.14159 print(string.format("%o, %x, %X", 1024,4069,16382)) -->> 2000, fe5, 3FFE print(string.format("%s %q", "Hello", "Corona SDK!"))-->> Hello "Corona SDK!" 


string.lower (s) / s: lower ()



The function converts all characters in a string to lower case:



 print(string.lower('Hello World!')) -->> hello world! 


string.upper (s) / s: upper ()



The function converts all characters in the string to uppercase:



 print(string.upper('Hello World!')) -->>HELLO WORLD! 


string.rep (s, n) / s: rep (n)



The function is passed a string and the number n, the string is returned repeated n times:



 local s = 'Corona ' print(s:rep(3))-->> Corona Corona Corona 


string.reverse (s) / s: reverse ()



The function returns the passed string with characters in reverse order:



 print(string.reverse('9876543210')) -->0123456789 


string.match (s, pattern [, index])

s: match (pattern [, index])



The string.match function finds the occurrence in string s according to the regular expression pattern and returns the capture parameters. About captures using regular expressions will be described in detail in the appropriate section. The function has an optional index parameter, which is equal to 1 by default and determines from which account the entry into the template is to be captured, it should be noted that the negative Index value, by analogy with string.find, is not supported:



 local reg = " (%w+):(%d+)"--    2  local s = " force:30, speed:25"--     local key, value = s:match(reg, 2)--    print(key, value)-->> speed 25 


string.gmatch (s, pattern)

s: gmatch (pattern)



The string.gmacth function is in many respects similar to the string.macth function, but it is intended to be used as an argument in a loop (for more information about loops, see the corresponding section). string.gmacth returns the captures of all occurrences in the string, i.e. no need to specify index, it looks like the following example:



 local reg = " (%w+):(%d+)"--    2  local s = " force:30, speed:25"--     for key, value in s:gmatch(reg) do--     print(key, value) end -->> force 30 -->> speed 25 


Cyclic capture is the most powerful tool for Lua to use which can greatly facilitate many routine operations for parsing complex string values.



string.sub (s, i [, j])

s: sub (i [, j])



The string.sub function returns the substring of the passed string. The substring starts with the i-th character. If the third argument j is not specified, the substring will end at the end of the string. If the third argument is specified, the substring ends with the jth character. If i or j has a negative value, the count comes from the end of the line. I will give examples of use:



 local s = 'To be or not to be' print(s:sub(7))-->>or not to be print(s:sub(7,12))-->>or not print(s:sub(-5))-->>to be print(s:sub(4,-3))-->>be or not to print(s:sub(-8,-4))-->>ot to 


string.gsub (s, pattern, replace [, n])

s: gsub (pattern, replace [, n])



The string.gsub function is one of the most powerful functions of the language. The function has several applications in the simplest case; it replaces in the string s all matches specified in the pattern with the value specified in replace in all places, using n you can limit the number of substitutions, the function will return the resulting string and the number of substitutions:



 local s = 'dust ist fantastisch' print(s:gsub('s','S'))-->>duSt iSt fantaStiSch 4 local s = 'lalalalala' print(s:gsub('a','A',3))-->>lAlAlAlala 3 


As in the case of string.find, a regular expression (capture) can be used as a search pattern. Capture arguments can be placed according to indices% index_number:



 print(string.gsub("lalalalala", "(l)(a)", "%2%1")) --  l  a --      -->> alalalalal 5 


As the replace parameter, a function can be used while parameters captured by a regular expression will be passed to it as parameters.



 string.gsub("12 23 34", "(%d+)", print)--     -->> 12 -->> 23 -->> 34 




A few words about utf-8.



Most of the functions of the string library cannot correctly work with the utf-8 format for this reason, strings with a national encoding and other special characters will not be correctly processed. To solve these problems, the Corona SDK has a separate utf library, which has both analogs of functions from the string library and several of its facilities. This library will be discussed in more detail in the context of studying the Corona SDK, or readers can study it themselves.



Type table



The type table (table) is the most basic type of data representation in Lua, in the most general sense, almost all the main entities in a language are tables, even source files. How to create tables and how to work with them:



 local t = {}--   t['key1'] = 'name1'--  key1   "name1" t['key2'] = {}--  key2   t['key2']['key3'] = 123--  key3   key2 


The exact same table can be initialized in another way:



 local t = { key1 = 'name1', key2 = { key3 = 123, }, } 


notice these entries are identical:



 t['key1'] = 'name1' t.key1 = 'name1' 


there is a sense in the first record type only if a numeric value is used as a key:



 t[1] = 111--  t.1 = 111--    


The values ​​recorded in the table are readable and writeable:



 print(t.key1)-->> name1 t.key1 = 'name2' print(t.key1)-->> name2 


To clear the entire contents of the table, you can use one of the following methods:



 t = {}--   -     table.remove(t)--     


If you want to delete one of the table keys, this can be done in two ways:



 t.key1 = nil-- nil   table.remove(t, key1)--     


The most natural way to initialize tables in Lua is to create a numbered array, this is done in the following way:



 local t = {23, 45, 3.14, 'vasia', {12, 'a'}} 


In fact, if you do not specify the key when initializing the table, the numbering occurs in the order of increasing starting 1 (for most developers, numbering from 0 is more natural, but in Lua it is not so, you need to remember about it), so The initialized table actually looks like this:



 local t = { [1] = 23, [2] = 45, [3] = 3.14, [4] = 'vasia', [5] = { [1] = 12, [2] = 'a', }, } 


As you can see, “under the hood” quite significant transformations took place with the data. Numbered tables in Lua have special properties, for example, by adding the # symbol to the table name, you get the number of strictly numbered values ​​in the table:



 print(#t)-->>5 print(#t[5])-->>2 (     5) 


If you add to the table a new strictly numbered key obtained through # the size of the table will increase:



 t[#t+1] = 'kolia' print(#t)-->> 6 


If you delete one of the keys by assigning nil, for example, the key [3] the continuous part of the numbered array decreases to just 2 keys [1] and [2], which cannot lead to further errors due to misunderstanding, for this reason I advised above to delete Keys from the table using table.remove, as with this, if you delete the key, the other strictly numbered values ​​will be shifted:



 --   t[3] = nil print(#t)-->> 2 --   table.remove(t,3) print(#t)-->> 5 


After correct removal of the key, the table will look like:



 local t = { [1] = 23, [2] = 45, [3] = 'vasia', [4] = { [1] = 12, [2] = 'a', }, [5] = 'kolia', } 


You can add other unnumbered keys to the strict-numbered table, this will not affect the performance of the table, but these keys will also not be taken into account when getting the size through #:



 t.key = 'name1' print(t.key, #t)-->> name1 5 


To bypass all the numbered values ​​of the table by the cyclic operation, there is a function ipairs, it is used as an argument of the for loop by analogy with string.gmatch:



 for key, value in ipairs(t) do print(key, value) end -->> 1 23 -->> 2 45 -->> 3 vasia -->> 4 table: 00000000 -->> 5 kolia 


If you want to bypass the cycle all values ​​including those not strictly numbered, use the pairs function:



 for key, value in pairs(t) do print(key, value) end -->> 2 45 -->> key name1 -->> 3 vasia -->> 1 23 -->> 4 table: 00000000 -->> 5 kolia 


Note? that when using pairs, the sequence of outputting values ​​is not strict, but in general rather confusing, this should be taken into account. In conclusion, I want to note that you can use pairs / ipairs as you pass the value of the table, or by creating it directly into a call like this:



 for key, value in ipairs{10,20,30} do print(key, value) end -->> 1 10 -->> 2 20 -->> 3 30 for key, value in pairs{key1 = 34,key2 = 65, key3 = 12} do print(key, value) end -->> key1 34 -->> key3 12 -->> key2 65 


Function type



The function type has all user-defined functions and standard language functions. I will give an example:



 local summ = function(a,b) return a + b end print(type(summ))-->> function print(type(print))-->> function 


You will learn more about how to use functions in the appropriate section.



Thread type



Thread is a separate thread of code execution. I will try to briefly explain what it is. All code of your Lua project is executed in a single execution thread, if there is a need to execute an object of type thread is created in a separate thread. The following code is used for creation:



 --  local co = coroutine.create(function () --    end) print('TYPE: '..type(co))-->> thread 




thread, , coroutine.resume thread. - . coroutine.yield(), . coroutine.resume. , . Those. coroutine.resume .



 --  local co = coroutine.create(function () local num = 1--     while true do print(num)--   num = num + 1-- coroutine.yield()--   resume end end) print('TYPE: '..type(co)) --     coroutine.resume(co)-->> 1 coroutine.resume(co)-->> 2 coroutine.resume(co)-->> 3 




, . , , .



userdata



userdata Lua , C(). Those. Lua userdata. , .



Conclusion



Lua , Corona SDK , .

Source: https://habr.com/ru/post/344312/



All Articles