unknown_document

We couldn't find that page... Were you looking for one of these?


Return Values
Values are returned by functions using the return statement, optionally followed by a value or a comma-separated sequence of two or more values. Let's take a quick at how this works with the following function definition which returns two values: local two = function () return 1 , 2 end We can collect both return values by defining variables for each expected value: local a , b = two () print ( a ) -- 1 print ( b ) -- 2 Unlike some programming languages, it is not an error to collect a different number of values than the function returns. If we only assign one of the return values to a variable, the left-most return value is assigned, while the others are simply ignored: local a = two () print ( a ) -- 1 print ( b ) -- nil Likewise, if we assign more values to variables than are returned by the function, the extra variables are simply assigned a value of nil : local a , b , c = two () print ( a ) -- 1 print ( b ) -- 2 print ( c ) -- nil
Arguments
One of the key advantages of functions is that they allow a piece of code to be written then called repeatedly. This is accomplished by allowing arguments to be passed to functions, then have the function work with those arguments to produce the desired output. Most functions are defined to accept a fixed number of arguments . When values are passed to the function they are taken positionally and assigned to the variable name for the corresponding argument. When arguments are passed into a function, they become locally-scoped within the function, just like variables that are defined inside the function definition, which allows Lua to support nesting and recursive functions . Lua is quite forgiving regarding values passed to functions, when a function call contains fewer values than arguments it simply assigns nil to the unused variables. When too many values are passed, it simply ignore them extra values. For example, the following function definition expects 2 values to be passed into the function when it is called: local test = function ( a , b ) print ( a ) print ( b ) end Let's now call this function: print ( test ( 1 , 2 )) which produces the output: 1 2 Ok, as expected. Let's now try calling the function with a single argument: print ( test ( 1 )) which produces the output: 1 nil Whereas many languages will raise an error when a function is called with the incorrect number of arguments, Lua simply assigns nil to unused variables. Finally, let's try passing extra arguments to our function: print ( test ( 1 , 2 , 3 )) which produces the output: 1 2 Again, no error was raised, and the extra argument was simply ignored.
Function Definition
Like most programming languages, Lua supports the ability to add new functionality by implementing functions . At a high-level, functions are "callable units" of code that can optionally accept 1 or more parameters, perform some operations on them, then optionally return 0 or more results. Lua supports two different, but equivalent, styles for defining functions . The first style creates a variable then assigns a function to that variable: -- local name = function(args) local sum = function ( a , b ) -- function body return a + b end The second style is equivalent to the first, but the order of the function keyword and the variable name are reversed. -- local function name(args) local function diff ( a , b ) --function body return a - b end In both cases, the function's arguments are defined as a sequence of 0 or more comma-separated variable names in the function definition. Which style to use is generally a matter of personal coding style, but the second style allows functions to be stored in tables which allows them to operate as "methods" when implementing classes with Lua.
Lua
Lua is a lightweight, cross-platform, high-level programming language that has become increasingly-popular as an embedded scripting language. Lua is often praised as a clean, simple, easy to learn scripting language that is applicable to a wide range of tasks. Today Lua can be found in a wide range of applications ranging from wezterm to xplr and neovim . Let's get started.
Working with Lua Patterns
In the previous section we looked at format strings , which provide a convenient way to create consistent, well-formatted strings that can contain unique values. In this chapter we look at patterns , which are roughly the opposite: patterns allow us to extract values from well-formatted strings. A pattern defines a specification that describes the content of a strings . When a pattern is compared to a "target" string , if the pattern describes the string we say that the target "matches the pattern". Patterns are generally composed of a sequence of smaller patterns , called "atoms". These atoms are arranged in a specific sequence to create the specification. As a simple example, let's build a pattern that matches phone numbers, then we will describe the process in more detail in the coming sections. We will assume phone numbers matching the format: +1(234)567-8910 The first step is to break this string into a sequence of components: +[country code]([area code])[prefix]-[line number] Next, we need to specify each component in terms of regular expressions, then combine them into the pattern. One possible final pattern might be: +%d[(]%d%d%d[)]%d%d%d-%d%d%d%d which is made up of: A literal + The " character class " %d , which specifies that the characters in those locations must be digits, Literal ( and ) surrounding a sequence of 3 digits %d Sequences of 3 and 4 digits, separated by a literal - If we apply this pattern to our target phone number, the target string is returned (which is a truthy value indicating that a match occurred. For comparison, we include a few other target strings with slightly different format, which produce nil (i.e. falsy ) values indicating that a match did not occur. local pattern = "+%d[(]%d%d%d[)]%d%d%d[-]%d%d%d%d" print ( string.match ( "+1(234)567-8910" , pattern )) -- +1(234)567-8910 print ( string.match ( "+1(23)4567-8910" , pattern )) -- nil print ( string.match ( "(234)567-8910" , pattern )) -- nil With that quick introduction, let's learn how to create patterns.
Lua's Reserved Words
Lua defines a number of reserved words , which are words that have special meaning to Lua and therefore cannot be used as identifiers such as variable or function names. It is an error to use any of the following: and break do else elseif end false for function if in local nil not or repeat return then true until while
Lua's Repeat Loop
Like the While Loop , the Repeat Loop is a "condition-controlled" loop. Unlike the While Loop , the Repeat Loop guarantees that the loop body is executed at least one time, then stops when the controlling condition is true . Repeat loops follow the pattern: repeat -- loop body -- repeat as long as boolean expression is true until [ boolean expression ] As a simple example, let's sum up all numbers from 0 to 4 using a repeat loop : local x = 0 local result = 0 repeat result = result + x x = x + 1 until x >= 5 print ( result ) -- 10 The break statement can be used to terminate a repeat loop early, just like a while loop . The following is equivalent to the previous example. local x = 0 local result = 0 repeat result = result + x x = x + 1 if x >= 5 then break end until false print ( result ) -- 10 Note that in this case we set the boolean expression to false , so that it continues to execute until the break is encountered. As while the while loop , care must be taken to prevent infinite loops . Finally, let's implement the final example from the while loop section using a repeat loop , showing that the repeat loop also terminates when a return statement is encountered: local function sum () local x = 0 local result = 0 repeat result = result + x x = x + 1 if x >= 5 then return result end until false end print ( sum ()) -- 10
Lua String Length
Lua includes two methods of determining the length of a string ; the length operator # and the library function string.len . Whereas similar functions in most high-level languages return the length as the number of characters in the string , Lua returns the number of bytes of memory occupied by the string. In many common cases such as ASCII these yield the same result, but case should be taken to watch for unexpected results. Let's take a look at a few examples: local x = "abcd" local y = "ab cd" print ( # x ) -- 4 print ( # y ) -- 5 print ( string.len ( x )) -- 4 print ( y : len ()) -- 5 In this case, we defined two strings containing only ASCII characters, and demonstrated how to find the length using both the length operator and the string.len library function. Both examples are basically the same, although the second example include a space ( " " ) to show that these are counted, just like any other character. Now, let's take a look at a few unicode strings, which can each occupy multiple bytes: local x = "中文" local y = "zhōng wén" local z = "😊" -- careful! print ( # x ) -- 6 print ( # y ) -- 11 print ( # z ) -- 4 print ( string.len ( x )) -- 6 print ( y : len ()) -- 11 print ( z : len ()) -- 4 These are (probably) not the results that we would have expected. Our main point is to make you aware of how Lua treats string length , and how it might produce unexpected results.
Control Structures
Lua implements several of the basic control structures that might be expected in a programming language. Here is a quick summary of the available options, then we will get into the details in the coming sections: Control Type Structure Conditional If-Then Condition-controlled Loop While Condition-controlled Loop Repeat Count-controlled Loop Numeric For Collection-controlled Loop Generic For
Format Strings
We have already learned that Lua strings are immutable , and that changing a string produces a copy of the string which can make string construction through concatenation inefficient. String buffers can provide a more efficient means of constructing a string from one or more sub-strings in many situations. Lua format strings are another option that can provide a flexible and more efficient alternative. Format strings are strings that contain "placeholders" that identify where values are to be inserted, and a simple "format specifier" that defines how each value should be formatted. These strings are then passed to the string.format library function with the values to be used to render the final string. Let's look at an example: print ( string.format ( "%s %d %f" , "hello" , 123 , math.pi )) -- hello 123 3.141593 This example used a simple template, consisting of placeholders %s , %d , and %f , which were populated by the values "hello" , 123 , and math.pi , respectively. Placeholders are defined by % , followed by the format specifier that has the format: %[flags][width][.precision]type where specifiers in brackets are optional, and behave slightly differently depending on the type specifier. Learning to use Format strings effectively takes some experience, trial, and error, so we will touch on the highlights and provide examples to show some common use-cases. Type Specifier The type specifier indicates how the corresponding value should be formatted. Most of the type options relate to numerical values, and render them in various ways: Type Meaning Example Value Result s String %s abc abc d or i Decimal or integer %d 123 123 f Float %f math.pi 3.141593 e Scientific notation %e math.pi 3.141593e+00 E Scientific notation %E math.pi 3.141593E+00 g Autoformat %g math.pi 3.141593 G Autoformat %G math.pi 3.141593 o Octal %o 123 173 x Hexadecimal %x 123 7b c Character %c 97 a q Lua code %q "abc" "abc" Two Scientific notation options are available, with the difference being whether e or E are used to identify the exponent. There are also two Autoformat options, which evaluate the value and automatically determine whether to format the value as a float or using scientific notation . The two autoformat options differ in how they format the value when scientific notation is used, where g and G correspond to e and E format, respectively. Character formatting converts a character code (typically an ASCII code) into the corresponding character, and behaves like the string.char library function. Finally, the q type specified is a Lua-specific option that renders the value in a format that can be parsed and executed by Lua. Width The width field specifies the minimum number of characters of width the value should occupy. If the value requires fewer than the specified number of characters, then this many characters are occupied. If the value requires more characters, then use the required number of characters. We can see how this behaves by formatting math.pi to a range of widths : print ( string.format ( "%1f" , math.pi )) -- 3.141593 print ( string.format ( "%2f" , math.pi )) -- 3.141593 print ( string.format ( "%3f" , math.pi )) -- 3.141593 print ( string.format ( "%4f" , math.pi )) -- 3.141593 print ( string.format ( "%5f" , math.pi )) -- 3.141593 print ( string.format ( "%6f" , math.pi )) -- 3.141593 print ( string.format ( "%7f" , math.pi )) -- 3.141593 print ( string.format ( "%8f" , math.pi )) -- 3.141593 print ( string.format ( "%9f" , math.pi )) -- 3.141593 print ( string.format ( "%10f" , math.pi )) -- 3.141593 print ( string.format ( "%11f" , math.pi )) -- 3.141593 Not much happens when small width values are specified, then as the width exceeds 8 characters the value becomes "padded" with empty spaces. This is the default behavior, though we can change that with the Flags specifier. Flags As we saw in the previous section, when a value requires fewer characters of width that are specified the value becomes "left-padded" with spaces. Format strings provide a few flags that allow this behavior to be changed: Flag Meaning Example Value Result None Default %4d 1 1 - Left Align %-4d 1 1 + Show both + and - signs %+4d 1 +1 0 When width is present, zero-pad the value. %04d 1 0001 space prepend a space ( " " ) for positive values % 4d 1 1 Precision The precision field usually specifies a maximum limit of the output, depending on the particular formatting type. The precision specifier defines the maximum width of the output, which is accomplished by rounding the value to the right of the decimal point to the specified number of digits: print ( string.format ( "%4.0f" , math.pi )) -- 3 print ( string.format ( "%4.1f" , math.pi )) -- 3.1 print ( string.format ( "%4.2f" , math.pi )) -- 3.14 print ( string.format ( "%4.3f" , math.pi )) -- 3.142 print ( string.format ( "%4.4f" , math.pi )) -- 3.1416 print ( string.format ( "%4.5f" , math.pi )) -- 3.14159 print ( string.format ( "%4.6f" , math.pi )) -- 3.141593 print ( string.format ( "%4.7f" , math.pi )) -- 3.1415927 print ( string.format ( "%4.8f" , math.pi )) -- 3.14159265 print ( string.format ( "%4.9f" , math.pi )) -- 3.141592654 print ( string.format ( "%4.10f" , math.pi )) -- 3.1415926536 print ( string.format ( "%4.11f" , math.pi )) -- 3.14159265359