﻿ ﻿Extending Lua with Functions - Beginning Lua Programming (2007)

# Beginning Lua Programming (2007)

### Chapter 3. Extending Lua with Functions

One of the key concepts in programming is abstraction, which means ignoring unimportant details. Consider the following set of instructions:

1. Get two slices of bread, a jar of peanut butter, a jar of jelly, and a butter knife.

2. Using the butter knife, spread a thin layer of peanut butter on one side of one piece of bread.

3. Using the butter knife, spread a thin layer of jelly on one side of the other piece of bread.

4. Attach the two pieces of bread together by pressing the peanut-buttered side of the one to the jellied side of the other.

Now compare those instructions with the following:

1. Make a peanut-butter-and-jelly sandwich.

The first set of instructions is less abstract than the second, because it contains details that would only be helpful to someone naive in the ways of sandwich preparation. The second set of instructions abstracts away these details. Consider the following code:

print(1)

print(2)

print(3)

print(4)

print(5)

print(6)

print(7)

print(8)

print(9)

print(10)

This is less abstract than the following code:

for I = 1, 10 do

print(I)

end

Both examples do the same thing, but the second one takes advantage of the fact that Lua knows how to count. This demonstrates one of the benefits of abstraction — there’s less to type! A related benefit is that it makes code easier to understand: When you know how for loops work, you can tell at a glance that the second example prints the numbers from 1 to 10, whereas you’d only know that for sure about the first one if you were to proofread it and make sure that (for instance) it doesn’t print two sixes in a row.

Functions are the most important means of abstraction in Lua. You’ve already used one function in the previous chapter: print. In the following example, the print function is being told to do its thing with two pieces of data — the string "The answer is" and the number 42:

Another way of saying this is that print is being called with two arguments. print is only one of many built-in functions that Lua has, but almost any program you write will involve you defining your own functions.

Take a look at the following example:

> function Greet(Name)

>> print("Hello, " .. Name .. ".")

>> end

> Greet("John")

Hello, John.

> Greet("Jane")

Hello, Jane.

> Greet("Aloysius")

Hello, Aloysius

The first line ("function Greet(Name)”) tells Lua that you’re defining a function, that the function’s name will be Greet, and that it will take one argument, whose value will be placed into the variable Name. When the function is called, the second line concatenates the string "Hello, " with (the contents of) Name and a period, and prints the result. The last line of the function tells Lua that you’re done defining the function. A function definition like this is a statement.

The function is then called three times, each time with a different name as an argument, and prints a greeting customized for a person with that name. Because the details of how to greet someone are only in one place, you only need to make any change you want once, rather than every time you greet someone.

The inside of a function definition is executed only when or if the function is called. In the preceding example, because the call to print is inside Greet, nothing is printed when Greet is defined, but something is printed each time Greet is called. This point may seem obvious, but if you’re a beginning programmer, you might find yourself forgetting it when confronted with more complex pieces of code.

Functions can have more than one line of code inside them. In fact, they can include all the things covered in the preceding chapter. Here’s one that includes assignment and an if control structure:

function Greet(Name)

if Name == "Joe" then

else

MsgStr = "Hello, " .. Name .. "."

end

print(MsgStr)

end

For that matter, functions can even contain no lines of code, in which case they do nothing. Functions can also take any number of arguments, or none, as in the following example:

>function NoNameGreet()

>> print("Hello.")

>> end

> NoNameGreet()

Hello.

> function TwoNameGreet(Name1, Name2)

>> print("Hello, " .. Name1 .. " and " .. Name2 .. ".")

>> end

> TwoNameGreet("Mutt", "Jeff")

Hello, Mutt and Jeff.

If a function is called with more arguments than it was written for, the extra arguments are thrown away, like this:

> NoNameGreet("Cathy")

Hello.

> TwoNameGreet("Larry", "Moe", "Curly", "Shemp")

Hello, Larry and Moe.

If a function is called with fewer arguments than it was written for, the remaining arguments are (inside the function) set to nil as follows:

> function Print2Args(Arg1, Arg2)

>> print(Arg1, Arg2)

>> end

> Print2Args("1st argument", "2nd argument")

1st argument 2nd argument

> Print2Args("1st argument")

1st argument nil

> Print2Args()

nil nil

Notice that this behavior (discarding extra arguments and setting missing ones to nil) exactly parallels the behavior of multiple assignment (described in Chapter 2):

> Varl, Var2 = "1st value", "2nd value", "3rd value"

> print(Var1, Var2)

1st value 2nd value

> Var1, Var2 = "1st value"

> print(Var1, Var2)

1st value nil

This chapter is all about functions. It explains how to do the following:

· Give names to pieces of code and refer to them by those names (this is one of the most important methods used to structure a program)

· Execute a file that contains Lua code

· Use variables that are only valid in limited parts of a program

· Use the same variable name to refer to different variables in different parts of a program

Return Values

Functions—both ones built into Lua and ones that you define—can return values. This means that a function call can result in a value that you can then pass to another function, use in a variable assignment, or otherwise operate on. In other words, function calls are actually expressions that, like print and Greet, you can use as statements.

Using a Function that Returns a Value

You can return values from functions that you’ve defined. But first, you should see how to get a return value from a function that’s already built into Lua.

Lua’s built-in type function is a good example of a function that returns a value. Here are some examples of this function:

> print(type(42))

number

> print(type("Hello, Aloysius."))

string

> print(type(true))

boolean

> print(type(type(true)))

string

> print(type(nil) .. type(false))

nilboolean

> SomeType = type(42)

> print(SomeType)

number

The type function takes one argument, which can be any value. It always returns a string that names the datatype of its argument, which will be—one of the following eight strings: "boolean", "function", "nil", "number", "string", "table", "thread", or "userdata". So, when type is called with a number as an argument, it returns the string "number"; when type is called with nil as an argument, it returns the string "nil"; and so on.

These eight strings represent all eight Lua types. Booleans, nils, numbers, and strings were covered last chapter. Right now you’re learning about functions. Tables, threads, and userdata will be explained in Chapter 4, Chapter 9, and Chapter 13, respectively.

As the preceding examples show, a call to type is an expression and can be used wherever an expression is legal. You can use it as the argument to another function:

print(type(type(true)))

Or as an operator’s operand:

print(type(nil) .. type(false))

Or in an assignment:

SomeType = type(42)

If you call type in the interpreter without doing anything with its value, nothing happens (the value is thrown away):

> type(42)

>

This is why the type result has been passed to print in the preceding examples.

Defining a Function that Returns a Value

Unsurprisingly, Lua makes it easy to define your own functions that have return values. You use the return statement.

The following function, Average, uses return to return the average of its two arguments:

> function Average(Num1, Num2)

>> return (Numl + Num2) / 2

>> end

> Average(0, 10)

> print(Average(0, 10))

5

> print(Average(Average(10, 20), Average(30, 40)))

25

The first time Average is called, nothing is done with the result, so the result is thrown away, and you never see it. The second time it is called, the result (5) is passed to print, so you do see it. On the next line, Average is called twice, and the results are passed to a third call of Average. This is equivalent to the following:

Avg1, Avg2 = Average(10, 20), Average(30, 40)

print(Average(Avg1, Avg2))

Using the return values of function calls as arguments to other function calls is very common. If carried to an extreme, it can get a bit hard to read, in which case assigning intermediate results to variables (like Avg1) can make things more legible.

This Average function can only average two numbers. In the next chapter, you’ll learn how to write a function that can average however many numbers you give it.

Functions, just like the break statement and the if, for, and while control structures, alter the flow of control through a program. The return statement also alters the flow of control.

In the following example, return is used to jump past the bottom of the function:

> -- Returns true if Str has an even number of characters;

> -- otherwise returns false:

> function EvenLen(Str)

>> if #Str % 2 == 0 then

>> return true

>> else

>> return false

>> end

>> print("This will never get printed!")

>> end

> print(EvenLen("Jane"))

true

> print(EvenLen("Joe"))

false

>

The if tests whether the length of Str is evenly divisible by 2. If it is, the function immediately returns true, which means that the rest of the function (in this case, the final print call) never gets executed. If the length is not evenly divisible by 2, the function immediately returns false, and the printis again not reached.

If this sounds familiar, it’s because return is very similar to break, which you learned about in the last chapter. In fact, there are two differences:

· break exits the innermost loop; return exits the innermost function (functions, like loops, can be nested).

· Because loops don’t return values, break cannot be followed by an expression like return can.

Like break, return must be the last statement in a block. In the last chapter, an incomplete list of blocks was given (do blocks; for, while, and repeat loops; branches of if statements). The only other blocks are functions and chunks. A chunk is a piece of code executed as a unit, such as the following:

· A complete file

· A single line typed into the Lua interpreter without causing the continuation prompt to appear

· Multiple lines typed into the Lua interpreter, of which all but the last cause the continuation prompt to appear

Again as with break, if you want (for debugging purposes) to return from the middle of a block, just use a dummy do block like this:

> function ReturnFromMiddle()

>> print("Does get printed")

>> do return true end

>> print("Doesn't get printed")

>> end

> ReturnFromMiddle()

Does get printed

>

In the last chapter, you saw how break can sometimes make loops, especially long ones, harder to understand. For similar reasons, returning from the middle of functions, particularly long ones, can make them harder to understand. To verify that the last line of EvenLen will never be executed, you need to examine the whole function, a small hardship which would be greater with a larger function.

This book often has you write functions like this:

function EvenLen(Str)

if #Str % 2 == 0 then

Ret = true

else

Ret = false

end

return Ret

end

The return value is assigned to Ret in the middle of the function, but Ret is only returned at the very end, so the function has only one exit point, while the earlier version of EvenLen had two. (There’s actually something wrong with this exampleRet is visible outside the function, when it really should be the function’s own private variable. You’ll learn how to avoid this later in this chapter.)

The practice of having only one exit point from each block is part of what is known as structured programming, a school of thought most identified with programming pioneer Edsger Dijkstra (1930-2002). Structured programming is much less controversial now than when it was first introduced in the 1960s, but it is by no means universally regarded as correct. We, the authors of this book, think of it as a rule of thumb to which exceptions can be made.

Returning Nothing

Before you learned about return, you saw how to write functions that don’t include return. What do such functions return? It’s easy enough to find out. When print is called with no arguments, it just prints an empty line, like this:

> print()

>

If you create a function that does nothing and has no return statement, and print its result, you get an empty line as shown here:

> function DoNothing()

>> end

> print(DoNothing())

>

If functions like this returned nil , you would see it here. This is a strong hint that functions that don’t use return really do not return a value. You can verify this by trying to print the following DoNothing return value, which results in type complaining that it wasn’t given a value:

> print(type(DoNothing()))

stdin:1: bad argument #1 to 'type' (value expected)

stack traceback:

[C]: in function 'type'

stdin:1: in main chunk

[C]: ?

To explicitly return no value, use return with no value. The following version of DoNothing behaves exactly the same as the previous version:

function DoNothing()

return

end

And the following function also does nothing and returns nothing:

function DoNothing()

do return end

print("This will never print.")

end

Not having a return statement at the end of a function has exactly the same effect as having a return that returns no values.

Returning Multiple Values

So far, you’ve seen functions that return one value and functions that return no values. Functions can also return more than one value, and this turns out to be a particularly handy feature of Lua.

Here’s a function that takes three arguments and returns all of them.

> function ReturnArgs(Arg1, Arg2, Arg3)

>> return Argl, Arg2, Arg3

>> end

> print(ReturnArgs(1, 2, 3))

1 2 3

> print(ReturnArgs(ReturnArgs(1, 2, 3)))

1 2 3

> A, B, C = ReturnArgs("alpha", "bravo", "charlie")

> print(A, B, C)

alpha bravo charlie

To return multiple values, simply separate the values with commas. Just from reading the following line, you might think that print is being given only one argument:

print(ReturnArgs(1, 2, 3))

But it actually gets three arguments—the three values returned by ReturnArgs. The next line is just a generalization of this. ReturnArgs is given three arguments; it returns three values; those three values are given to another call of ReturnArgs, which itself returns three values; and those values are given to print (which prints them):

print(ReturnArgs(ReturnArgs(1, 2, 3)))

You can also use a call to a function that returns multiple values as the right side of an assignment, like this:

A, B, C = ReturnArgs("alpha", "bravo", "charlie")

You just saw that you can use a function that returns multiple values as the first and only argument to another function (in which case it’s as though the function was called with multiple arguments) or as the entire right-hand side of an assignment (in which case it’s as though multiple values were assigned). What if you use a function that returns multiple values as one of several arguments to another function, or as only part of the right side of an assignment? As you know, if you call a function with more than one argument, then the arguments are separated with commas. The same applies to assignment statements that assign more than one value and return statements that return more than one value. These lists of zero or more (in the case of functions and return) or one or more (in the case of assignment) values are called value lists.

When you call functions in value lists, their return values are adjusted. This is similar to the process of adjustment (described in Chapter 2) that happens in assignment statements.

Using Multiple-Valued Functions in Value Lists

Here’s how multiple-valued functions work in various positions in value lists of various lengths, using the ReturnArgs function defined in the previous section:

> print(1, ReturnArgs("a", "b", "c"))

1 a b c

> print(ReturnArgs(1, 2, 3), "a")

1 a

> print(ReturnArgs(1, 2, 3), ReturnArgs("a", "b", "c"))

1 a b c

The rule that Lua follows it this:

If a function call returning multiple values is the last (or only) expression in a value list, then all the function’s return values are used. If a function call returning multiple values is in a value list but is not the last expression, then only its first return value is used; its remaining return values are discarded.

This explains why the following:

print(ReturnArgs(1, 2, 3), ReturnArgs("a", "b", "c"))

printed this:

1 a b c

ReturnArgs(1, 2, 3) was not the last expression in the print list of arguments, so only its first return value (1) was used, and its second and third values were thrown away. The ReturnArgs("a", "b", "c") was the last expression in print’s argument list, so all three of its return values ("a", "b", and "c") were passed as (the second, third, and fourth) arguments to print.

The rule also applies to value lists with more than two expressions in them, such as these:

> print(

>> ReturnArgs(1, 2, 3),

>> ReturnArgs(4, 5, 6),

>> ReturnArgs(7, 8, 9),

>> ReturnArgs(10, 11, 12))

1 4 7 10 11 12

Although these examples were given using the print function, the value lists in return and assignment statements work the same way:

> function Test()

>> return ReturnArgs(1, 2, 3), ReturnArgs(4, 5, 6)

>> end

> print(Test())

1 4 5 6

> A, B, C, D = ReturnArgs(1, 2, 3), ReturnArgs(4, 5, 6)

> print(A, B, C, D)

1 4 5 6

Using Valueless Functions in Value Lists

What about functions that return no values, such as the following:

> function DoNothing()

>> end

> print(1, DoNothing())

1

> print(DoNothing(), 2)

nil 2

> print(DoNothing(), DoNothing())

nil

This is just an application of the same rule: When the call to DoNothing is the last expression in the value list, no adjustment is made and no corresponding value is passed to print, and when the call to DoNothing is not the last expression in the value list, it is adjusted from no values to one value, namely nil. Here’s the rule rephrased to cover functions that return no values:

If a function call is the last (or only) expression in a value list, then all (if any) values returned by the function are used. If a function call is in a value list but is not the last expression, then its first return value (or nil, if it returns nothing) is used and any remaining return values are discarded.

This rule (adjust every expression except the last to one value) may seem more complicated than necessary, but there is good reasoning behind it. If every expression in a value list were adjusted to one value, there would need to be a special way to override this, which would make the ability of Lua functions to return multiple values harder to use. If no expressions in a value list were adjusted to one value, then any function returning less or more than one value would throw off the positioning of everything that came after it in the value list.

As you saw with type, a function call used as a statement is adjusted to no return values, because there’s nowhere for those values to go.

As covered in the previous chapter and earlier in this one, the whole value list involved in an assignment or a function call is adjusted to the right size by discarding values or adding nils. That adjustment happens after the adjustment of individual expressions in the value list that this section has been describing:

> A, B = DoNothing(), 1, 2

> print(A, B)

nil 1

> A, B, C = ReturnArgs(1, 2, 3), 4

> print(A, B, C)

1 4 nil

To force a function call at the end of a value list to be adjusted to one value, surround the whole function call (including its parentheses) with parentheses:

> print("a", (ReturnArgs("b", "c", "d"))) —

a b

> print("a", (DoNothing()))

a nil

You’ve seen three uses for parentheses: function calls, controlling precedence in expressions, and function definitions. It may seem as though adjusting to one value is yet another use of parentheses, but in Lua, these are the same type of parentheses used to control precedence. You can use a function to return less or more than one value only when a call to it is the last expression in a value list. Wrapping such a call in parentheses has no effect on precedence, because there are no operators and therefore no precedence to control, but it does cause the last expression in the value list to no longer be a function call (even though it contains one), and to therefore no longer be eligible for multiple- or zero-value treatment.

return is not a function. This means that you should not surround whatever comes after it in parentheses, unless you want to force adjustment to one value as shown in the following example:

> -- This example requires the ReturnArgs function used

> -- earlier.

> function Test()

>> return (ReturnArgs(1, 2, 3))

>> end

> print(Test())

1

Chunks as Functions

Earlier in this chapter, a chunk was defined as a piece of code executed as a unit. The simplest example is code typed into the interpreter. When you enter a line into the interpreter, it checks whether you typed any complete statements. If so, it executes those statements as a chunk. If not, it prints a continuation prompt so you can finish. After it has amassed a whole number of statements, it compiles (converts) them into bytecode—an internal representation much more efficient than the text that you type in (which is also known as source code). This bytecode is meant for the internal component of Lua also known as the interpreter, which is the second meaning of the term interpreter mentioned in the previous chapter. When there is a possibility for confusion, the first interpreter can be called lua or the command-line interpreter, and the second can be called the bytecode interpreter.

The command-line interpreter and the bytecode interpreter are not two independent things. Rather, the command-line interpreter uses (and depends on) the bytecode interpreter.

After a chunk has been compiled into bytecode, it is a function (albeit one without a name). This means that chunks, including those typed into the interpreter, can be returned from the following:

> return

>

The return can even come from deep within a chunk, like this:

> for I = 1, 10 do

>> print(I)

>> if I == 5 then return end

>> end

1

2

3

4

5

>

If values are returned, lua passes them to print so you can see them, as shown here:

> return nil, "Hello", nil

nil Hello nil

This is how the equal-sign typing saver described in the last chapter works. When the interpreter sees a chunk that starts with an equal sign, it replaces the equal sign with "return ” before compiling the chunk like this:

> =nil, "Hello", nil

nil Hello nil

When a chunk typed into the interpreter is executed as a function, no arguments are passed to it.

Another important type of chunk is a file containing Lua code. Such a file is often called a script.

Try It Out

Unlike code typed directly into the interpreter, scripts are self-contained programs, which you can run repeatedly without having to type them in again. The following very simple script gives a greeting that is traditional in programming examples.

1. Create a file with the following contents and name it hello.lua:

-- This is the first file-based example in the book.

print("Hello, world!")

2. Access your system’s shell, and make sure you’re in the same directory as the file you just created (as described in Chapter 1). Then type the following and press Enter:

lua hello.lua

You should see the following:

Hello, world!

How It Works

When lua is started with a filename, it loads that file as a chunk and executes it. As with any chunk, a file can be returned from it, and values can be returned from it, but if the file is executed as shown in this example, these values will simply be thrown away. Arguments can be given to a file, as you’ll learn in the next chapter.

From here on, many of the examples will be presented as scripts to be executed by giving the filename to lua.

If you don’t want to have to type lua every time you run a file like this, you can make it directly executable. On Unix-like platforms this is done by making its first line something like#!/usr/local/bin/lua or # ! /usr/bin/env lua, and marking the file as executable withchmod a+x followed by the file’s name. (If Lua saw#! in the middle of a script, it would complain, but if it sees# as the very first character, it just skips to the second line.)

There are several ways to do it on Windows. Ussing hello.lua as an example, one method is to make a file calledhello.cmd that consists of a line like this:

@Lua "C:\Your\Dirs\Here\Hello.Lua" %*

Or if that doesn’t work because you are running an earlier version of Windows, you can use the following method, which limits the number of command-line arguments to nine (replace"C:\Your\Dirs\Here\"with the full path to the Lua file):

@lua "C:\Your\Dirs\Here\hello.lua" %1 %2 %3 %4 %5 %6 %7 %8 %9

The.cmd file must be in a directory in your system’s search path. After you do this, typinghellowill run the file.

You can also execute a string as a chunk. First use the built-in function loadstring to convert it to a function, and then call the function like this:

> Fnc()

Hello!

loadstring is an excellent example of the usefulness of multiple return values. If it succeeds in converting the string to a function, it returns that function; otherwise, it returns nil and an error message. That’s demonstrated by the following example, which also shows that loadstring takes an optional second argument—a a string used as a name for the chunk in any error messages:

> Fnc, ErrStr = loadstring("print(2 + + 2)", "A STRING CHUNK")

> if Fnc then

>> Fnc()

>> else

>> print(ErrStr)

>> end

[string "A STRING CHUNK"]:1: unexpected symbol near '+'

You can use the vararg mechanism described in the next chapter to access any arguments given to the function returned by loadstring (although not in Lua 5.0).

Like all chunks, a chunk compiled by loadstring has no access to local variables from other chunks. For example:

> Test = "global"

> do

>> local Test = "local"

>> Fnc() -- This prints Test's global value.

>> end

global

loadstring may seem like a very powerful function, but it’s seldom necessary. If you feel a need to use it, chances are that what you want to do should be done another way instead (with the closures described later in this chapter, for example, or with the getfenvand setfenv functions described in the next chapter). An exception to this is a program that (like the Lua interpreter) accepts code while it’s running, and runs that code. That type of thing is the ideal use of loadstring.

Variable Scope

In the last chapter, you saw that the variable created by a for loop is only visible inside the loop, and that a variable outside the loop can have the same name without them affecting each other. (Visible here means that it can be assigned to and its value can be read.) This is possible because Lua, like most modern programming languages, has variable scopes, which are regions within which certain variables are visible.

In early computer languages, all variables were in the same scope, which made it hard to write large programs, because you needed to make sure that the same name wasn’t used for two different things.

The first step in understanding scopes is learning the distinction between a function’s actual arguments and its formal arguments. This is explained by the next section.

Actual and Formal Arguments

In the following example, what is PrintArg’s argument?

> -- Prints its one argument:

> function PrintArg(Arg)

>> print(Arg)

>> end

> PrintArg(true)

true

There are two answers to that question. The argument PrintArg is defined with is Arg, but the argument it’s called with is true. The arguments that a function is defined to take are called formal arguments; the arguments that it is called with are called actual arguments.

This terminology is not totally standardized. For instance, some people call formal arguments parameters and reserve the word argument for actual arguments.

Formal arguments are just the names by which actual arguments are referred to inside a function when it is called. This is why using something other than a name as a formal argument is an error, such as the following:

> function Oops(true)

stdin:1: <name> or expected near 'true'

Local Variables

A function’s formal arguments are only visible inside the function, and any variable from outside the function is only visible if it does not share a name with a formal argument. For example:

> Arg, NotShadowed = "Outside 1", "Outside 2"

>

>> -- Prints its one argument and the value of NotShadowed:

> function ScopeTest(Arg)

>> end

>

> ScopeTest(true)

true Outside 2

> print(Arg)

Outside 1

When ScopeTest is called, a new variable is created, named Arg, and the actual argument for ScopeTest is assigned to it. Because this variable is only visible inside the function, it is called a local variable. When the value of Arg is printed, it’s the local Arg (whose value is true) that gets printed, and not the outer Arg (whose value is "Outside 1"). For this reason, the local Arg is said to shadow the outer Arg. On the other hand, NotShadowed, which does not share a name with any variable local to the function, is not shadowed, and is therefore accessible in the normal way.

After ScopeTest returns, the outer Arg is unaffected.

Scopes can be nested inside each other, as shown in this rather contrived example:

> function ScopeTest2(LclA)

>> print("LclA is " .. LclA)

>> for LclB = 1, 5 do

>> print("LclB is " .. LclB)

>> LclA = LclA + 1

>> end

>> print("LclA is now " .. LclA)

>> end

>

> ScopeTest2(100)

LclA is 100

LclB is 1

LclB is 2

LclB is 3

LclB is 4

LclB is 5

LclA is now 105

The scope of LclA is the whole function. The scope of LclB is just the loop. The example also shows that you can assign to local variables from containing scopes.

Functions and for loops create their own local variables, but you can create local variables too.

This example introduces the keyword local:

> function ScopeTest3(Lcl)

>> for I = 1, 5 do

>> Lcl = Lcl .. "a"

>> print(Lcl)

>> local Lcl = ""

>> Lcl = Lcl .. "z"

>> print(Lcl)

>> end

>> print("The loop is done.")

>> print(Lcl)

>> end

>

> ScopeTest3("")

a

z

aa

z

aaa

z

aaaa

z

aaaaa

z

The loop is done.

aaaaa

local Lcl = "" is a statement that creates a new local variable named Lcl and initializes it to the empty string. This new local variable’s scope starts on the statement after the local statement. Because it’s inside the scope of another variable also named Lcl (the function’s formal argument), it shadows that outer variable.

Every time the local statement is executed, a new local variable is created and initialized. That’s why the outer Lcl becomes a longer and longer string of a’s, whereas the inner Lcl is never longer than one z, because it keeps getting recreated and hence doesn’t remember its previous value.

The scope of a local variable created with the local statement has to end somewhere. In this example, it ends at the end of the loop (the same place that the scope of the loop variable I ends). You can see that this is true, because when the value of Lcl is printed after the loop is done, it’s the outerLcl whose value get printed.

A local variable’s scope extends to the end of the innermost block that encloses it. A block is a do block, the body of a while or for loop, the body of a repeat loop plus its until expression, a branch of an if statement, a function, or a chunk.

Figure 3-1 shows all the scopes in ScopeTest3, and clearly illustrates why the two Lcls are called outer and inner. The scope of the outer Lcl starts at the top of the function’s body and ends at the bottom of the function’s body; the scope of the I loop variable starts at the top of the loop body and ends at the bottom of the loop body; the scope of the inner starts right after the local statement and ends at the bottom of the loop body. Figure 3-1

Variables from outer scopes are always visible in inner scopes, unless they are shadowed. This is easier to show using the following do blocks to delimit scopes without altering control flow:

> do

>> local A = "A1"

>> do

>> local B = "B1"

>> do

>> local A = "A2"

>> do

>> local B = "B2"

>> B = "still B2"

>> end

>> do

>> local C = "C1"

>> print(A, B, C)

>> end

>> end

>> end

>> end

A2 B1 C1

The inner A is printed because it shadows the outer one, but the first B is printed because the second B is not in a containing scope. By the time C’s scope starts, the second B scope has already ended. Figure 3-2 illustrates this: Figure 3-2

One of the benefits of indenting by block is that it makes scopes easier to see. To find out where the inner Lcl’s scope ends in ScopeTest3, all you need to do is find the first line below the local line that’s farther to the left—Lcl’s scope includes everything up to that line:

function ScopeTest3(Lcl)

for I = 1, 5 do

Lcl = Lcl .. "a"

print(Lcl)

local Lcl = ""

Lcl = Lcl .. "z"

print(Lcl)

end

print("The loop is done.")

print(Lcl)

end

As mentioned earlier (and illustrated by the positioning of the boxes in Figures 3-1 and 3-2), the scope of a variable created by a local statement doesn’t begin until the following statement. This means that if a variable name appears on both sides of a local statement’s equal sign, the one on the left names the variable whose scope is about to begin, and the one on the right names a variable in a containing scope:

> do

>> local Lcl = "aardvark"

>> -- The first Lcl's scope starts here.

>> local Lcl = Lcl .. "zebra"

>> -- The second Lcl's scope starts here.

>> print(Lcl)

>> -- Both scopes end here.

>> end

aardvarkzebra

A chunk is a block, which means that if a local variable is not contained within any other blocks, its scope ends when the chunk ends. This means that a local variable is never visible in two different files. It also means that a local variable is never visible in two different chunks of interpreter input. Here’s an example:

> City = "New York"

> local City = "London"

> print(City)

New York

In this example, the first line gives a value to the variable City, which is not a local variable. The second line creates and initializes a local variable, also named City, which is forgotten about as soon as the line is done executing. The third line prints the value of a variable named City. Because there is no containing block with a local variable of that name, the City from the first line is used.

Variables that aren’t local are called global variables. They are called this because they are visible globally, everywhere in the program, even across different chunks. Their scopes begin and end at the beginning and end of the program. Not counting for loop variables, all the variables you used in the previous chapter were global.

You can shadow global variables by local variables as follows:

> Var = "global"

> do

>> local Var = "local"

>> print(Var)

>> Var = "still local"

>> print(Var)

>> end

local

still local

> print(Var)

global

You can create and initialize multiple local variables at the same time. Other than creating new local variables, you follow the same rules as for multiple assignment (for example, nils are used if the list of

values is too short):

>do

>> local A, B = 1, 2

>> print(A, B)

>> local A, B = 1

>> print(A, B)

>> local A, B = 1, 2, 3

>> print(A, B)

>> end

1 2

1 nil

1 2

You can create local variables without initializing them. This is exactly like initializing them to nil :

> do

>> local A

>> print(A)

>> local B, C

>> print(B, C)

>> end

nil

nil nil

Whether you make the nil implicit (local A) or explicit (local A = nil) is a stylistic choice. Generally, you shouldn’t use the explicit version if the nil will never be seen because it will be replaced with another value. An example of this is the following rewritten version of the EvenLen function:

Remember that the second version ofEvenLen given earlier (the one with only one exit point) had a problem. The problem was that, before returning its return value, it stored it in the global variableRet, which means that if Ret was used as a global anywhere else, calling EvenLen would rudely overwrite its value. (You can verify this by calling EvenLen and then printing Ret.) This is exactly the problem that local variables are meant to solve. Here, EvenLen is rewritten so that the Ret it uses is only visible inside it.

function EvenLen(Str)

local Ret

if #Str % 2 == 0 then

Ret = true

else

Ret = false

end

return Ret

end

Don’t make the mistake of thinking that regular assignment (an equal sign but no local keyword) is for assigning to global variables and the local keyword is for assigning to local variables. Rather, regular assignment assigns to either globals or locals (whichever is visible, scopewise), and the local keyword creates new locals and optionally assigns initial values to those very locals.

Understanding Side Effects

If a statement or expression causes something to change, this is called a side effect, such as when the print function changes what’s on the screen. For example, the following function changes the value of the global variable Gl :

The Val variable created in this example is not part of the side effect, because creating a new local variable doesn’t change the value of a variable that already exists.

function SetGl(Val)

Gl = Val

end

On the other hand, the type function has no side effects—all it does is return a value. However, this value may then be used by another function or statement that does have a side effect.

Ordering Side Effects

If two functions are free of side effects, it doesn’t matter which order they’re called in. In the following example, it is impossible to tell whether the type on the left was called before or after the one on the right, but that’s okay, because all that matters is that the left one’s return value was used as the first print argument (and the right return value as the second):

> print(type(1), type("a"))

number string

If two functions do have side effects, though, you can see which order they’re called in. This will be easiest to demonstrate with a function that has both a return value and a side effect:

-- Prints a message with Val, then returns Val:

function PrintReturn(Val)

print("Returning: " .. tostring(Val))

return Val

end

PrintReturn takes a single argument. It prints a message that it is about to return this argument, and then it does so. It uses the built-in Lua function tostring to convert the argument to a string (otherwise the concatenation operator would choke on nil and Booleans):

> print(PrintReturn(1), PrintReturn(2), PrintReturn(3))

Returning: 1

Returning: 2

Returning: 3

1 2 3

This example showed that the three calls to PrintReturn are made from left to right, but don’t rely on this —the order is actually undefined and only happens to be left to right in the current implementation. If you want to make sure that function calls are made in a particular order, make them part of different statements like this:

> do

>> local Val1 = PrintReturn(1)

>> local Val2 = PrintReturn(2)

>> local Val3 = PrintReturn(3)

>> print(Val1, Val2, Val3)

>> end

Returning: 1

Returning: 2

Returning: 3

1 2 3

This holds for function calls used in expressions, too —they’re done left to right, but don’t rely on it:

> print(PrintReturn(1) + PrintReturn(2))

Returning: 1

Returning: 2

3

Similarly, the current implementation of Lua assigns from right to left, but this behavior shouldn’t be relied on:

> A, A = 1, 2

> print(A)

1

What is guaranteed is that all function calls to the right of an assignment will be made before any of the variables to the left are assigned to. This is just a special case of the rule that all expressions to the right of an assignment are evaluated before any assigning is done. (If it weren’t for that rule, you couldn’t use multiple assignment to swap values, which was demonstrated in the previous chapter.) In the following example, when 1 is added to B, the initial value of B is used, and when 1 is added to A, the initial value of A is used. Only after both calls to PrintReturn are made (with these incremented values) do A and B get new values:

> A, B = 1, 10

> A, B = PrintReturn(B + 1), PrintReturn(A + 1)

Returning: 11

Returning: 2

> print(A, B)

11 2

It’s also guaranteed that any function call used as an argument (or part of an argument) to another function will be made before the other function is called. So, the innermost PrintReturn is called before the one whose parentheses it is inside (which would be true even if the outer PrintReturn never did anything with its argument):

> print(PrintReturn(PrintReturn(1) + 1))

Returning: 1

Returning: 2

2

Functions that don’t have side effects are easier to decipher than those that do because you don’t have to think about how many times or in what order they’re executed. Side effects that are only visible within a small part of the program (that is, assigning to a local variable) are easier to decipher than those visible throughout the whole program, because you don’t have to consider them while thinking about the rest of the program. This doesn’t mean that you should completely avoid side effects. It does mean that, when faced with the choice of writing a function with side effects or without, you should write it without side effects unless there’s a good reason to write it with them. It also means that, unless a variable needs to be visible throughout the entire program, it should be made local with as narrow a scope as possible.

The and and or operators have a special behavior regarding side effects. This behavior is called short-circuit (or shortcut) evaluation, and it is demonstrated next.

Short-Circuit Evaluation

Remember that the length operator # gets the length of a string. If it’s given something that doesn’t have a length (a Boolean in the following example), it will error out, but notice that there is no error when Len is given a Boolean, even though Len returns an expression that includes an attempt to get its argument’s length:

> print(#true)

stdin:1: attempt to get length of a boolean value

stack traceback:

stdin:1: in main chunk

[C]: ?

>

> -- Returns Val's length, or false if Val isn't a string:

> function Len(Val)

>> return type(Val) == "string" and #Val

>> end

>

> print(Len(""))

0

> print(Len("abc"))

3

> print(Len(true))

false

In the previous chapter, you learned that and uses its second operand as its result only if its first operand is true. However, if its first operand is false, then not only does it not use its second operand as its result, but it doesn’t even evaluate the second operand, so any side effects the second operand might have had will not happen. This also applies to errors; giving a Boolean to the # operator causes an error, but in the previous example, Val is only given to # if it’s a string. The following examples, which use the PrintReturn function, will make this clearer:

> print(PrintReturn(1) and PrintReturn(2))

Returning: 1

Returning: 2

2

> print(PrintReturn(1) and PrintReturn(false))

Returning: 1

Returning: false

false

> print(PrintReturn(nil) and PrintReturn(2))

Returning: nil

nil

> print(PrintReturn(nil) and PrintReturn(false))

Returning: nil

nil

The first operand of an and is always evaluated (which means any side effects it has will happen). The second operand is only evaluated if it needs to be—if the first operand is false (false or nil), then that’s the result of the and, which means that there’s no need to evaluate the second operand.

This also applies to or — if the first operand of or is true (anything other than false or nil), then that’s the result, and the second operand is not evaluated. For example:

> print(PrintReturn(1) or PrintReturn(2))

Returning: 1

1

> print(PrintReturn(1) or PrintReturn(false))

Returning: 1

1

> print(PrintReturn(nil) or PrintReturn(2))

Returning: nil

Returning: 2

2

> print(PrintReturn(nil) or PrintReturn(false))

Returning: nil

Returning: false

false

Every function, even a supposedly side effect-free function like type, has the side effect of taking awhile to execute. Normally, this can be ignored, but not if a function takes a particularly long time to execute, or if it’s in a time-critical section of a program. To see what this has to do with short-circuit evaluation, imagine that you have a function called Search that always returns some true value and takes a long time to run. It may or may not have been run earlier in the program. If it was run, its result will be in the variable SearchResult. In this situation, the following statement is a concise way of printing the search result while making sure that Search is not called unnecessarily:

print(SearchResult or Search(SearchStr))

Short-circuit evaluation doesn’t do anything that couldn’t be done with if statements—and vice versa, for that matter. Use whichever one is easier to understand in a given case.

Functions Calling Functions

From within many of the preceding functions, you called print. You can also call your own functions from within functions.

The Call Stack

When a function calls another function, the calling function gets put on hold while the called one is doing its thing. Lua keeps track of which function is active and which ones are on hold with something called the call stack. Explaining how the call stack works will require an example (given in the following Try It Out) in which function calls are nested within other function calls.

Try It Out

Use Creating Nested Function Calls

1. Save the following code under the filename nestedcalls.lua:

-- A demonstration of functions calling functions.

function A()

B()

print(" Just exited B")

end

function B()

C()

print(" Just exited C")

end

function C()

print(" Inside C")

end

A()

print("Just exited A")

2. As you did with hello.lua earlier, run it by typing this into your shell:

lua nestedcalls.lua

You should see this:

Inside C

Just exited C

Just exited B

Just exited A

How It Works

Lua keeps a stack of information about all currently running functions. It’s called a stack because things are only put onto or taken off of the top. When a function is called, information about it is put on the top of the stack (making the stack taller), and when a function returns, that function’s information is removed from the top of the stack (making the stack shorter). Because this stack grows every time a function is called, it’s called the call stack. The information about one function call is said to occupy one stack frame.

A stack is also used to keep track of C function calls. This type of stack is called theC stack, and it’s separate from Lua’s call stack. Functions written in C also use a stack to interact with Lua, called the Lua API stack, and it is actually a little window on part of the call stack. This glosses over some details, but if you really want to know how it works, look at Lua’s source code.

In this example, the prints are formatted so as to be more and more indented as the stack gets taller. At the stack’s tallest point—the line where Inside C is printed — the stack frame at the top of the stack (not counting print’s stack frame) contains (among other things) the current location inside C. (Locationhere means the location of control: which statement is being executed and which expression is being evaluated.) The stack frame underneath that contains the current location inside the function that called C, namely B. This is the point to which control will return whenC returns. The next stack frame contains the current location inside A, and the bottom one contains the current location inside the function that called A, which is the whole file. (Remember that files are chunks, which are executed as functions.) All of these locations are highlighted here:

-- A demonstration of functions calling functions.

function A()

B()

print(" Just exited B")

end

function B()

C()

print(" Just exited C")

end

function C()

print(" Inside C")

end

A()

print("Just exited A")

These locations will be listed (in stack order) if an error happens inside C. For instance, if two nils are added together like this:

function C()

print(nil + nil)

print(" Inside C")

end

then the result will be three About to enter messages, followed by the error message, followed by a stack traceback, which is a multiline message showing the current location of control in each function on the stack, from the top down:

lua: nestedcalls.lua:16: attempt to perform arithmetic on a nil value

stack traceback:

nestedcalls.lua:16: in function ‘C'

nestedcalls.lua:11: in function ‘B'

nestedcalls.lua:5: in function ‘A’

nestedcalls.lua:21: in main chunk

[C]: ?

The bottom of the stack is [C]: ?. This just means that the main chunk was called by a C program (the Lua interpreter).

You’ll learn more about stack tracebacks in Chapter 6. The reason for introducing the concept of the call stack now is that it makes it much easier to explain the concepts of recursion, stack overflow, and tail calls.

Recursion

If a function calls itself, it is said to be recursive. Lua uses the call stack to store local variables, which means that multiple calls to the same function can be active at the same time without one call’s local variables stomping on those of another call.

Recursion is most often used when the problem to be solved is defined in terms of itself. The factorials in the previous chapter are an example of this: a number’s factorial is defined as that number times the factorial of that number minus one (for example, the factorial of 5 is 5 times the factorial of 4). By itself, this is a circular definition and hence useless. Circularity is avoided by defining the factorial of 0 to be 1. This is easily translated into a Lua function. One branch of an if statement handles the base case—the part of the definition that isn’t self-referential. The if’s other branch handles the self-referential, or recursive, case:

> -- Returns the factorial of N:

> function Fact(N) >> local Ret

>> if N == 0 then

>> -- Base case:

>> Ret = 1

>> else

>> -- Recursive case:

>> Ret = N * Fact(N - 1)

>> end

>> return Ret

>> end

>

> for N = 0, 5 do

>> print(N .. "! is " .. Fact(N))

>> end

0! is 1

1! is 1

2! is 2

3! is 6

4! is 24

5! is 120

A step-by-step breakdown of the call Fact(2) would look like this:

1. N is 2. Because it is not equal to 0, Fact is called recursively with 1 as an argument.

2. This recursive call to Fact creates a new variable N (local to this call) and sets it to 1. This N is completely independent of the N from the previous call. Because it’s not 0 , Fact is called yet again, with 0 as an argument.

3. At this point, the call stack is at its tallest—three stack frames taller than before the first call to Fact was made. This third call does take the base case, returning 1 .

4. Control returns to the second call, which receives the 1 returned by the third call. It multiplies this 1 by N, which is also 1 , and returns the result (also 1 ).

5. The first call receives this 1, multiplies it by 2, and returns the result (also 2). After the return, the stack will be back to the height it started at.

If you’ve worked with recursion before, this will all be old news to you. If you haven’t worked with recursion before and you’re having trouble wrapping your head around it, try going step-by-step through another call or two to Fact with slightly higher numbers. You’ll find that, to keep track of each call’s location of control and value of N, you need to simulate a stack (mentally or on paper).

Stack Overflow

If the call stack gets too tall, it can run out of space. This is called stack overflow, and it is an error.

Fact only works on non-negative integers. If it’s given a negative or fractional number, a stack overflow occurs, as shown in the following example:

> print(Fact(-1))

stdin:8: stack overflow

stack traceback:

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in function 'Fact'

stdin:8: in main chunk

[C]: ?

A negative or fractional number is handled with the recursive case, but the base case is never reached, which means that the stack gets taller and taller (which takes awhile) until it overflows, or tries to go beyond its maximum size. The stack traceback in the error message only shows the top and bottom of the stack (the dots represent the middle).

For most purposes, you are not likely to run out of stack space if your program isn’t buggy. Stack overflow is usually a sign of an infinite recursion, as the previous example shows. If you do want to keep the stack from growing unnecessarily, there are two ways to do it. One is to use iteration (a loop) instead of recursion, like this:

-- Returns the factorial of N (iteratively):

function Fact(N)

local Ret = 1

for I = 1, N do

Ret = Ret * I

end

return Ret

end

The other way is to make sure that a recursive call is a tail call, which means it has a certain form explained in the next section.

If for some reason you need to change how big the stack gets before it overflows, edit the value of LUAI_MAXCALLS in src/luaconf.h before compiling Lua. Due to the way the stack is grown, this value should be twice the maximum number of stack frames you need to use.

Tail Calls

In the recursive version of Fact, there’s still more work to be done after the recursive call returns. You need to multiply the recursive call’s result by N, and assign that value to Ret, which you must then return. Here’s how:

-- Returns the factorial of N:

function Fact(N)

local Ret

if N == 0 then

-- Base case:

Ret = 1

else

-- Recursive case:

Ret = N * Fact(N - 1)

end

return Ret

end

If there were nothing left to do but return the recursive call’s result after it returned, you wouldn’t need to make a new stack frame for it. Instead, you could overwrite the current function’s stack frame (the information in it no longer being necessary).

This type of function call whose result is immediately returned by the calling function is called a tail call. When Lua sees a tail call, it does the preceding optimization, reusing the calling function’s stack frame rather than making a new one. Therefore, the following function will run forever (or until interrupted), continually calling itself but never consuming more than one stack frame:

function ForeverTail()

return ForeverTail()

end

When you do interrupt it, it looks like the stack is big, but it isn’t really. Lua keeps track of how many tail calls have happened and shows them in the traceback, but they don’t take up any space in the actual call stack:

> ForeverTail()

stdin:2: interrupted!

stack traceback:

stdin:2: in function 'ForeverTail'

stdin:2: in function <stdin:1>

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

...

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

(tail call): ?

stdin:1: in main chunk

[C]: ?

In the following function, it may seem that there is nothing left to do after the call, and that the call is therefore a tail call:

function ForeverNotTail()

ForeverNotTail() -- Is this a tail call?

end

This is not a tail call, though, because there is something left to do before returning: the list of ForeverNotTail return values must be adjusted to zero. Therefore, ForeverNotTail, unlike ForeverTail, will overflow the stack.

A tail call is always a return statement whose expression is a single function call.

None of the following are tail calls—the first because there’s no return, the rest because the return’s expression is something other than a single function call:

Fun()

return Fun() + 1

return X and Fun()

return (Fun()) -- This expression is a single function call

-- surrounded in parentheses, which is different than the

-- required single function call (the parentheses adjust

-- Fun to one return value).

return Fun(), Fun()

A recursive function that uses a tail call to call itself is said to be tail recursive. The recursive version of Fact is not tail recursive, but you can rewrite it to be tail recursive by introducing an accumulator—a variable that keeps track of all the multiplications done so far:

-- Returns the factorial of N (tail-recursively). Calls

-- itself with two arguments, but when you call it, you need

-- supply only one argument (like the other Fact functions).

function Fact(N, Acc)

-- Initialize the accumulator to 1:

Acc = Acc or 1

if N == 0 then

-- Base case:

return Acc

else

-- Recursive case:

return Fact(N - 1, N * Acc)

end

end

This version of Fact will recurse forever (instead of overflowing the stack) if you give it a negative or fractional number.

Although none of the preceding examples show it, a tail call is still a tail call even if it’s not a recursive call.

Functions as Values

Functions are values (as are numbers, strings, Booleans, and nil). For example, take a look at the following:

print(type("Hello"))

This operates by looking in the global variable type, finding a function there, calling that function with the value "Hello", looking in the global variable print, finding a function there, and calling that function with the value returned by the function in type.

If you call type with a function as an argument, it returns the string "function":

> print(type(print))

function

Replacing Built-in Functions

You can demonstrate that functions are values by replacing the print function with your own function:

> -- Give the print function another name, so it';ll still be

> -- accessible:

> RealPrint = print

>

> -- Prints a message and its one argument:

> function FakePrint(Val)

>> RealPrint("Inside FakePrint:", Val)

>> end

>

> -- Replace print with FakePrint:

> print = FakePrint

> -- Use print:

> print("Hello")

Inside FakePrint: Hello

> print(true)

Inside FakePrint: true

> -- Undo the damage:

> print = RealPrint

> -- Back to normal:

> print("Hello")

Hello

> print(true)

true

There are two reasons that you need to assign the real print function to RealPrint before assigning the FakePrint function to print. One is to give FakePrint some way to print things; the other is to allow the real print function to be put back in its rightful place afterwards.

If you play around a bit, you’ll find that the Lua interpreter actually uses whatever function it finds in the global variable print to print any values returned from interpreted chunks, like this:

> print = FakePrint

> return "abc"

Inside FakePrint: abc

Comparing and Printing Functions

You can compare functions for equality (or inequality), like this:

> print = RealPrint

> print(print == RealPrint)

true

> print(print == type)

false

If you print a function (or convert it to a string with tostring), it will appear as the word function, followed by a colon, a space, and a number (a hexadecimal number on most systems):

> print(print)

function: 0x481720

The only thing you need to know about this number is that two different functions that exist at the same time will have different numbers.

Under the hood, this number represents the function’s location in memory.

Function Definitions as Assignments

Because functions are values and function names are variable names, it could be deduced that the function statement is a type of assignment. This is indeed true. Take a look at the function statement:

function name(formal arguments)

statements

end

This does exactly the same thing as the following assignment statement of the form:

name = function (formal arguments)

statements

end

To the right of the equal sign (and spilling out onto the next two lines) is a function expression —an expression whose value is a newly created function.

You can use a function expression wherever you can use any other expression. You can print it, pass it to another function, assign it, compare it, and so on. In the following example, function()end is a function expression representing a function that takes no arguments, does nothing, and returns nothing:

> print(function() end)

function: 0x493888

> print(type(function() end))

function

As this example shows, you do not need to give a function a name. A function without a name is called an anonymous function. You can call an anonymous function by wrapping the function expression that created it in parentheses (and following that with the usual parentheses used in function calls), like this:

> (function(A, B)

>> print(A + B)

>> end)(2, 3)

5

Calling an anonymous function (or anything that doesn’t look like the part of a function call before the arguments) is yet another use for parentheses, but as far as Lua is concerned, these are the same parentheses used to control precedence and to adjust to a single value.

Every time a function expression is evaluated, a new function is created. That’s why DoNothing1 and DoNothing2 are not equal in the following example, even though the expressions that created them look alike:

> DoNothingl, DoNothing2 = function() end, function() end

> print(DoNothing1, DoNothing2)

function: 0x493f20 function: 0x493f38

> print(DoNothing1 == DoNothing2)

false

For the same reason, both times MakeDoNothing is called in the following example, it returns a different function, even though each of those functions is created by literally the same function expression:

> -- Returns a do-nothing function:

> function MakeDoNothing()

>> return function() end

>> end

>

> print(MakeDoNothing() == MakeDoNothing())

false

Two different function expressions or function statements will always create two different functions, even if the text of the expressions or statements is the same. A single function expression or statement will create two different functions if it is executed twice.

As shown by the MakeDoNothing example, you can return functions just like other values. In Lua, unlike in some other languages, there are no arbitrary limits on what can be done with functions (as compared with other values). For this reason, Lua functions are said to be first-class values.

Local Functions

You can also assign functions to local variables. This can be done either with a function expression, like this:

> do

>> local LclAverage = function(Num1, Num2)

>> return (Num1 + Num2) / 2

>> end

>> print(LclAverage(10, 20))

>> end

15

> -- This will print the global variable LclAverage, which

> -- will be nil:

> print(LclAverage)

nil

Or with a local form of the function statement, like this:

> do

>> local function LclAverage= function (Num1, Num2)

>> return (Num1 + Num2) / 2

>> end

>> print(LclAverage(10, 20))

>> end

15

> -- This will print the global variable LclAverage, which

> -- will be nil:

> print(LclAverage)

nil

Because they can be hidden from the rest of a program, local functions have the same benefits as local variables of other types. More specifically, a function is a good candidate for localization if it only makes sense in one small part of a program—especially if it’s a closure that will be recreated several times as a program runs.

Another use of local functions is to speed up time-critical loops. This works because access to local variables is faster than access to global variables. For example, if you use the (global) type function inside a loop that needed to run as quickly as possible, you could precede the loop with the following:

local type = type

However, optimizations like this should be done only if they’re necessary, as discussed in Chapter 4.

Because the scope of a variable created by a local statement starts on the next statement, creating a recursive local function like the following will not work because the F referred to inside the function is a global variable (or possibly a local in a containing scope):

local F = function()

code that does something or other

F() -- A failed attempt at a recursive call -- the local F

-- is not visible here.

more code that does something or other

end

Instead, you need to create the local first, and then assign the function:

local F

F = function()

something or other

F() -- This really is a recursive call.

more something or other

end

Conveniently, the local function statement does exactly that for you behind the scenes:

local function F()

something or other

F() -- This, too, really is a recursive call, because the

-- "local function" statement arranges for the body of

-- the function to be within the scope of the function';s

-- name.

more something or other

end

In the same way that an assignment such as A=5assigns to either a local variable or a global one (depending on whether a local variable named A is visible), a function statement such as function F() creates either a local function or a global one, depending on whether a local named F is visible.

Whitespace, Semicolons, and Function Calls

This is a convenient time to cover some topics that aren’t all directly related to functions.

Characters that have no visual appearance other than moving other characters farther apart (such as the space and newline characters) are called whitespace. Outside of strings, Lua is very tolerant of different uses of whitespace. It treats the following pieces of code the same:

for I=1,10 do local X=I*7 print(I,X)end--Cramped!

for

I

= 1

, 10 do

local X

= I * 7

print (

I , X )

end -- Spacy!!

The first example is cramped and hard to read, and the second is just silly, but in between these two extremes, you’ll see variation from programmer to programmer. In your own code, you should pick a whitespace style that is not too far from the mainstream, but you should also cultivate an eye for variations, so that if you work with other people on a project that has a consistent whitespace style, you can pick it up easily. For instance, did you notice that the comment markers in this book have spaces separating them from any code before or comments after them? Did you notice that commas in this book have spaces after (but not before) them?

Another point of variation among Lua programmers is the use of the semicolon. You can follow any statement by a semicolon if you want. For example:

> print("Test");

Test

Semicolons can ease the transition for programmers used to languages where semicolons are required. Most Lua programmers do not use semicolons, or if they do, they use them only to separate multiple statements on the same line, like this:

function Avg(A, B) local Sum = A + B; return Sum / 2; end

There is a situation where a semicolon is required, and it's related to a situation where a newline is pro-hibited. For example, Lua reads the following in a single chunk:

Fun1()

(function() return Fun2 end)()

But Lua doesn’t know whether this is supposed to be one statement (call Fun1 with no arguments, call its return value with the anonymous function as an argument, and call that function’s return value with no arguments) or two statements (call Fun1, and then call the anonymous function). For this reason, Lua doesn’t allow a newline before the open parenthesis of a function call, as in the following example:

> print

>> ("Lua")

stdin:2: ambiguous syntax (function call x new statement) near '('

If you follow this rule, and you still get the ambiguous syntax message, you’ll need to put a semicolon at the end of the statement before the line where the error occurs, like this:

> do

>> print("2 plus 3 is:")

>> (function(A, B)

stdin:3: ambiguous syntax (function call x new statement) near '('

> do

>> print("2 plus 3 is:");

>> (function(A, B)

>> print(A + B)

>> end)(2, 3)

>> end

2 plus 3 is:

5

A function call variant that you’ll run into is this: When a function is called with one argument, and that argument is a literal string, the parentheses can be left out. For example:

> print "with a space"

with a space

> print"or without"

or without

Upvalues and Closures

You saw earlier that if the same function statement or expression is executed twice, it creates two different functions. The reason for this is that two functions created by the same source code can act differently from each other if they have upvalues and are therefore closures. Definitions of these terms will have to wait until after the following example.

Defining Functions that Create Functions

You’ve already seen one function that created (and returned) other functions: MakeDoNothing. That was a bit boring, though, because even though it created a unique function each time it was called, all those functions did the same thing (which was nothing). The following function, MakeLessThan,creates less-than functions, each of which tests whether its argument is less than a particular number:

> -- Returns a function that tests whether a number is

> -- less than N:

> function MakeLessThan(N)

>> return function(X)

>> return X < N

>> end

>> end

>

> LessThanFive = MakeLessThan(5)

> LessThanTen = MakeLessThan(10)

> print(LessThanFive(4))

true

> print(LessThanTen(4))

true

> print(LessThanFive(5))

false

> print(LessThanTen(5))

true

> print(LessThanFive(9))

false

> print(LessThanTen(9))

true

> print(LessThanFive(10))

false

> print(LessThanTen(10))

false

Remember that when you call a function, a new local variable is created for each of its arguments. So when MakeLessThan is called with 5 as an argument, a local variable N is created and initialized to 5. Normally, this N would no longer be visible after MakeLessThan returns, but because there’s a function (the anonymous one after return) in N’s scope that uses N, N will last as long as the function does. MakeLessThan returns the function and assigns it to LessThanFive.

Next, MakeLessThan is called with 10 as an argument. At this point, a local variable N is created and initialized to 10. This is a newly created variable — it’s different from the other N created for the previous call. MakeLessThan returns a function that uses this new N, and this function is assigned to LessThan Ten. Calling LessThanFive and LessThanTen with various values shows that they live up to the names given to them. LessThanFive tests whether its argument is less than 5, and LessThanTen does the same with 10 .

When a function uses a variable that is local to a containing scope (such as N in this example), that variable is called an external local variable or an upvalue. The term "upvalue" is somewhat misleading, because an upvalue is not a value, but a variable used in a certain context. (The term dates back to Lua 3.1, when it was more accurate.) Despite this, it is used in this book because it’s in common use among Lua programmers, and it’s much shorter than the more accurate "external local variable." A function that has one or more upvalues is called a closure. (All functions, even those with no upvalues, are represented in the same way internally. For this reason, "closure" is sometimes used as a synonym for "function.")

Earlier it was said that local variables reside on the stack, but the stack is not a good place for long-term storage; when a function returns, its stack frame is abandoned, and when a function does a tail call, its stack frame is overwritten. Lua handles this by making sure that an upvalue is migrated from the stack to a safe place elsewhere in memory whenever the block it was created in is exited. Knowing that Lua initially stores local variables on the stack and migrates them elsewhere only if needed is good background information, but it is not strictly necessary for an understanding of either local variables or upvalues. An implementation of Lua could be written that always kept local variables somewhere other than the stack. It would act the same as the real implementation of Lua, except that it would be slower. (Actually, it would be different in one other way — it would not impose a limit on the number of local variables visible at one time. In practice, though, this limit in the real implementation is high enough that it is seldom if ever reached.)

You can call a function returned by another function directly, without giving it a name first. In the following example, MakeLessThan is called with 10 as an argument. The function it returns is then called with 5 as an argument. Because 5 is less than 10, true is printed:

> print(MakeLessThan(10)(5))

true

Two closures can share an upvalue, and upvalues can be assigned to. Both of these facts are demonstrated by the following example.

Defining Functions with Private State

The following MakeGetAndInc example makes and returns two functions: one that gets a value, and another that increments that value. These functions have private state—"state" because there’s changeable data that’s remembered in between calls, and "private" because this data is stored in a local variable visible to only these functions.

> -- Returns two functions: a function that gets N’s value,

> -- and a function that increments N by its argument.

>function MakeGetAndInc(N)

>> -- Returns N:

>> local function Get()

>> return N

>> end

>>

>> -- Increments N by M:

>> local function Inc(M)

>> N = N + M

>> end

>>

>> return Get, Inc

>> end

>

> -- Make two pairs of get and increment functions, one

> -- pair initialized to 0 and the other initialized to 100:

> GetA, IncA = MakeGetAndInc(0)

> GetB, IncB = MakeGetAndInc(100)

> -- Try them out:

> print(GetA())

0

> print(GetB())

100

> IncA(5)

> print(GetA())

5

> IncA(5)

> print(GetA())

10

> IncB(1)

> print(GetB())

101

> IncA(1)

> print(GetA())

11

As you can see, GetA and IncA both refer to the same N, but GetBand IncBboth refer to another N. GetA and IncA refer to the N created by the first call to MakeGetAndInc. The initial value of this N is 0, but it gets a new value every time IncA is called, and that new value is visible to GetA. GetB and IncB act the same way, except their value is stored in the N created by the second call to MakeGetAndInc.

This is also a good example of local functions. The names Get and Inc are only visible inside MakeGet AndInc. Because there’s no need to make them globally visible, it would have been a programming no-no to do so, because then MakeGetAndInc would not be usable in a program that already used one or both of those names for global variables.

There are two ways to accidentally use a global when a local was intended. One is to misspell the name of a local variable. The other is to forget the local keyword. Both of these are common sources of bugs.

Figuring Out Tricky Scope Situations

Every iteration of a for loop creates a new local loop variable. This is demonstrated by the following example:

> for I = 1, 2 do

>> if I == 1 then

>> function One()

>> return I

>> end

>> else

>> function Two()

>> return I

>> end

>> end

>> end

> print(One())

1

> print(Two())

2

Both One and Two return variables named I, but they are different variables — if they were the same I, then One and Two would return the same value.

for loops in Lua 5.0 actually did use the same loop variable for each iteration. If this example is tried in Lua 5.0, both One and Two return 2 because they refer to the same I, whose value when the loop ends is 2. Additionally, assigning to the loop variable (which is fine in Lua 5.1) has undefined behavior in Lua 5.0.

If you are ever in doubt about the scope of a variable, start from the statement where the variable’s name is used and search upwards for the following:

· A local statement that creates a variable of this name, or a local function statement that creates a function of this name

· A function definition (a function statement, local function statement, or function expression) that uses this name as a formal argument

· A for loop that uses this name as a loop variable

The first one of these that you run into whose scope extends to the statement where you started searching is the place where your (local) variable was created. (Remember that the scope of a variable created with local extends to the end of the innermost block that encloses it; this also applies to the scope of a function created with a local function statement.) If your search hits the top of the file without finding anything, the variable is global.

If your program is properly indented, this is a simple up-and-out search. You never need to look at a line that is indented further (to the right) than any line you have already looked at.

In the following example, PrintStr prints "Inside first do block"even though the call to it is in the scope of a local Str whose value is "Inside second do block":

> do

>> local Str = "Inside first do block"

>> function PrintStr()

>> print(Str)

>> end

>>end

> do

>> local Str = "Insid second do block"

>> PrintStr()

>>end

Inside first do block

It doesn’t matter where the call is. What matters is where Str is actually named, and that’s inside the definition of PrintStr (which is inside the first do block). A function cannot see local variables from the scope that called it (unless that happens to be the same scope in which it’s defined). This means that you can tell everything you need to know about a variable’s scope by looking at the program’s source code, without having to figure out which functions call which. In the same way, Lua itself can tell everything it needs to know about a variable’s scope when it compiles source code into bytecode, rather than having to wait till runtime (when the program is running).

Because variable scope is determined by the structure of a program’s source code, Lua is said to have lexical scope (The term "lexical" here means "based on source code.")

Actually, although whether a variable is global or local is determined lexically, Lua global variables are not lexically scoped. In most cases they can be treated as if they are; the exception happens when the function setfenv is used. You’ll learn aboutsetfenv in the next chapter.

Lua’s scoping rules allow arbitrarily complex combinations of global variables, local variables, closures with upvalues from multiple scopes, closures that share some upvalues but not others, upvalues that themselves contain closures, and so on. But the rules themselves are relatively simple, considering their power. Here they are:

· Each time a local or local function statement is executed, a new local variable (or possibly several, in the case of local) is created. Its scope extends downward to the end of the innermost enclosing block.

· Each time a for loop iterates, a new local variable (or possibly several, in the case of the generic for loop you’ll learn about next chapter) is created. Its scope extends to the end of the loop.

· Each time a function is called, a new local variable is created for each formal argument. The scope of these variables extends to the end of the function.

· If a variable was not created in any of the three aforementioned ways, it’s global.

· Each time a function or local function statement is executed, or a function expression is evaluated, a new function is created.

· There is no limitation on reading from or assigning to a visible local variable from within a function. (In other words, closures are possible.)

So if you find yourself not understanding why a program is doing what it’s doing, and you think it may be a scoping issue, ask yourself these questions:

· Is this a global or local variable?

Summary

In this chapter, you learned almost everything you need to know about functions. Namely:

· Functions allow complexity to be compartmentalized, and let you use the same code in different places in a program.

· A chunk is treated by Lua as a function.

· To run a Lua script, give lua a filename when you start it.

· Functions can take zero or more arguments and return zero or more values.

· When a function is called, a local variable is created for each of its formal arguments. These local variables are only visible inside the function.

· The local keyword and the for loop also create local variables.

· A function can call itself, which is called recursion. During recursion, or in any case where two calls are made to the same function, each call has its own local variables.

· A stack is used to keep track of function calls. You can us tail calls to avoid exhausting the large but finite space available for this stack.

· A function is a type of value (as are numbers, strings, Booleans, and nil). You can create functions at runtime, pass them as arguments, return them, assign them, compare them, used them without naming them, and so on.

· A function has full access to all local variables that are visible where the function is defined. A function that takes advantage of this is called a closure, and the variables from outer scopes that it accesses are called upvalues. You can use upvalues to create (from the same definition, at runtime) functions with different behavior, as well as to create functions that retain state between calls.

There are a couple remaining facts about functions that weren’t covered in this chapter. For example, how do you create a function that (like print) can take an indefinite number of arguments? You’ll learn this and more in the next chapter, which is about tables, Lua’s tool for combining multiple pieces of data into one. When you complete the next chapter, you’ll understand all of the basic elements of Lua, and you’ll be ready to start applying that knowledge in the chapter after that. This chapter ends with some exercises to test your understanding of functions. The answers are in the appendix.

Exercises

1. Write a TypedToString function that converts a value to a string and prefixes that string with the value’s type. (You don’t have to deal specially with the fact that a function converted to a string already has its type prefixed to it.)

> print(TypedToString("abc"))

string: abc

> print(TypedToString(42))

number: 42

> print(TypedToString(true))

boolean: true

> print(TypedToString(function() end))

function: function: 0x485a10

2. Write a function SumProd that returns both the sum and the product of two numbers:

>print(SumProd(1, 1))

2 1

>print(SumProd(2, 2))

4 4

>print(SumProd(3, 5))

8 15

3.Using SumProd from the previous exercise, what will the following print?

print(SumProd(3, 3), SumProd(5, 5))

4.What does the following print?

Continent = "North America"

function F(Continent)

Continent = "Australia"

end

F(Continent)

print(Continent)

5.The following MakeDotter function is intended to return a function that appends N dots to its argument (and returns the result). It almost works, but every time it’s used to make a new dot-ter function, the old ones stop working right. Why does this happen, and what one-line change can be made to make it work right?

> function MakeDotter(N)

>> Dots = ""

>> for I = 1, N do

>> Dots = Dots .. "."

>> end

>> return function(Str)

>> return Str .. Dots

>> end

>> end

>

> -- Make a function that appends one dot to its argument:

> OneDotter = MakeDotter(1)

> print(OneDotter("A"))

A.

> print(OneDotter("B"))

B.

> -- Make a function that appends three dots to its argument:

> ThreeDotter = MakeDotter(3)

> print(ThreeDotter("C"))

C. ..

> print(ThreeDotter("D"))

D. ..

> -- OneDotter now appends three dots instead of one:

> print(OneDotter("E"))

E. ..

﻿