unknown_document

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


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.
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
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.
Lua Comments
Before we get into Lua itself, let's first talk about comments . Comments are text annotations in code that are ignored when the script is executed, but help people reading the code understand it. We use comments throughout our examples to explain what is happening a different points in the code, as well as to show the values of variables and other important information. Because comments are used to help document this behavior, let's start with explain what they are and how to read them. There are two types of comments in Lua: Line Comments Line comments are delimited with two dashes, as in -- . When Lua encounters this delimiter, it ignores any content to the right of the delimiter. For example: -- This entire line is a comment print ( 123 ) --- The print statement executes, then this is ignored We will often use comments in examples to either: Explain the operations performed on a line, or Show the output or value of a variable on a line Block Comments Block comments are similar to line comments, except they apply to entire blocks of code. When there is an entire block of code to comment out, there are two choices. First, every line in the block case be commented with a line comment: -- local a = 123 -- -- print(a) -- -- a = 456 -- -- print(a) which is perfectly valid, though often less convenient than using a block comment: --[[ local a = 123 print(a) a = 456 print(a) ]] In the second example, the block comment starts with the -- , which is followed by double-square brackets [[ which define the start of the block comment. Everything between the start of the block and the end of the block, defined by the closing double-square brackets ]] , is considered a comment and ignored.
Lua Types
Lua is a dynamically-typed language, similar to Python . This means that there are no type definitions, and no need to declare the types of variables. Instead, the type is inferred from the value. This can be an advantage or a disadvantage, depending upon the context, but it is part of what allows Lua to have such a simple grammar. Let's now take a look at Lua's types:
Variable Scope in Lua
We learned in the previous section that variables consist of both a name and a value , and that after a variable has been declared, it is possible to "re-assign" values to the name . The important detail here is that each variable requires a unique name . Let's now take a look at an important aspect of variables, scope . Global Scope In the early days of programming, all variables were what we now call global variables , or variables that have (or exist in the) "global scope" . The global scope can be thought of as a single bucket of uniquely-named variables, that are accessible from anywhere. Programmers quickly discovered that this created a variety of problems, ranging from simple annoyances such as the need to define (and keep track of) many similarly-named variables to avoid "name collisions", to accidentally-created and difficult-to-find bugs related to different parts of the code operating on the same variables. Although global variables are generally discouraged today, they are supported by most languages, including Lua. In fact, variables created in Lua are global by default. While global variables might seem convenient, they lead to code that can be difficult to understand, debug, and maintain, which led the concept of scope and local scopes. Local Scope While we have described the global scope as a big bucket of variables, local variables can be thought of as smaller buckets of variables that are placed into that big global bucket. Local variables have their scope limited by the "location" in which they are defined: local variables defined in a file have their scope limited to that file. This allows the same variable names to be used in different files without risk of collision. local variables defined within a function are local to that function, which allows functions to be easily used across different files. Within a file or function, local variables defined within a block (such as a control structure are local to that block. Let's take a look at a few examples: local x = "file scope" print ( x ) -- file scope -- start an "if-then" block if true then -- this block has its own scope local x = "block scope" print ( x ) -- block scope end -- back in the file scope print ( x ) -- file scope local fn = function () -- this function has its own scope local x = "function scope" return x end -- although we are back in the file scope -- this prints the function's return value print ( fn ()) -- function scope -- this prints x from the file scope print ( x ) -- file scope
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 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.