First Steps - Beginning Lua Programming (2007)

Beginning Lua Programming (2007)

Chapter 2. First Steps

This chapter and the next two lay the foundation you need to understand the rest of the book. As such, they cover a great deal of material, although they're still very basic. If you've never programmed before, you'll learn a lot of new concepts; if you're an experienced programmer, you'll see a lot of things that you already know. In the latter case, you are encouraged to skim, but be warned: Some of the Lua building blocks covered in these three chapters may have no counterpart in the languages you are familiar with.

This chapter explains the:

· Arithmetic operations

· Variables and assignment

· Strings

· true, false, and nil values

· if statements and while, for, and repeat loops

Numbers and Arithmetic Operations: Basic Interpreter Usage

The Lua interpreter—lua—is a program that can execute Lua code that you type right after you type it.

This is how the term interpreter is used in this chapter, but it can also refer to a particular internal component of the Lua implementation—more on this in the next chapter and Chapter 10.

In this section, you explore the basics of using lua.

Addition, Subtraction, Multiplication, Division, and Exponentiation

Start with something simple—adding two and two. Access your system's shell, as described in Chapter 1. When you're there, type lua and press Enter (Return on some keyboards). You should see something like the following:

Lua 5.1.1 Copyright (C) 1994-2006 Lua.org, PUC-Rio

>

Typing lua starts the Lua interpreter. When it starts, it prints its version number and copyright information, and then it prints the following:

>

This Lua prompt tells you it's waiting for you to give it something to do.

Now type the following (the part you type is bold):

> print(2 + 2)

Then press Enter. You should see the following:

4

>

Lua looked between the parentheses, saw 2+2, added two and two, and followed the print command and output the result to the screen. It then displayed another prompt to tell you it was ready for more.

Lua can handle subtraction, negative numbers, numbers with decimal points, multiplication (using *), division (using /), exponentiation (using ^), and combinations of these. Here are some examples:

> print(2 - 2)

0

> print(-2 + -2)

-4

> print(2.5 + 2.75)

5.25

> print(3 * 3)

9

> print(100 / 4)

25

> print(3 ^ 2)

9

> print(5 * -5 + 1 + 1 + 0.5)

-22.5

Interacting with the Interpreter

The interpreter knows how to respond when you type Lua code that either contains a mistake or is incomplete. Sooner or later, you'll type something that makes no sense to Lua. In case you haven't already done this accidentally, now is the time to do it on purpose to see what happens. Typeprint (2 + + 2) and press Enter. Here's what you get:

> print(2 + + 2)

stdin:1: unexpected symbol near '+'

>

Lua sees something that doesn't make sense (two plus signs next to each other), so it prints a short explanation of why it doesn't make sense. The explanation is also known as an error message.

Because Lua is only a computer program, its explanations aren't always easy to understand at first, but this one (unexpected symbol near ‘ + ‘) is fairly straightforward. Next to a plus sign, Lua found something it wasn't expecting—in this case another plus sign.

After printing the error message, Lua displayed another prompt to let you know it was ready for more.

You'll get similar error messages if you leave out print or its parentheses, like this:

> 2 + 2

stdin:1: unexpected symbol near '2'

> print 2 + 2

stdin:1: '=' expected near '2'

If you type something that makes sense except that it's incomplete, Lua lets you finish it on another line. For example, press Enter before the close parenthesis, type the close parenthesis, and press Enter again, like this:

> print(2 + 2

>> )

4

Lua sees that the first line you typed was incomplete, so it printed >>. This is a continuation prompt, Lua's way of letting you know that it's waiting for you to finish what you started. When Lua got the close parenthesis on the next line, it was able to print the result.

Other Notations for Numbers

You can also write numbers using scientific notation, where the part before the upper- or lowercase e is multiplied by 10 to the power after the e. For example, 5e2 means 5 times 10 to the 2nd power, or 500. Scientific notation is normally used to write extremely large or extremely small numbers, or for Lua to print them. Here are some examples:

> print(5e2)

500

> print(5e-2)

0.05

> print(1.2193263111264E17 / 987654321)

123456789

> print(123456789 * 987654321)

1.2193263111264e+17

> print(2.3283064365387e-10 * 4294967296)

1

The numbers you use in daily life (and have used so far in this chapter) are decimal, or base 10. This means that there are 10 digits, 0-9. Lua also understands hexadecimal (base 16) numbers, using the letters a-f (or A-F) to represent 10 through 15. Hexadecimal numbers should start with 0x or0X. (That's a zero before the x, not a letter O.) They have to be integers (whole numbers). Take a look at these examples:

> print(0x1)

1

> print(0x10)

16

> print(0xff)

255

> print(0XA)

10

> print(0x03e8)

1000

> print(-0xf000)

-61440

> print(0xff.ff)

stdin:1: ')' expected near '.'

Lua 5.0 did not understand hexadecimal numbers.

Interpreter Know-How

Before learning any more about the Lua language, you should know a couple things about the interpreter.

Quitting the Interpreter

Sooner or later, you'll want to take a break. There are three ways to get out of the interpreter:

· Press Ctrl+C. This sends the interpreter what is called an interrupt signal. If the interpreter is waiting for you to type something, this will exit the interpreter. If the interpreter is stuck, doing something (or nothing) over and over without stopping, then this same key combination will get you back to the state where the interpreter is waiting for you to type something.

· Press Ctrl+Z (or on Unix-like platforms, including Mac OS X, press Ctrl+D) at the beginning of an empty line and press Enter. This sends an end-of-file (EOF). It's a signal to Lua that it should give up trying to get input from you.

· The most typing-intensive way to stop the interpreter is to type the following line:

os.exit()

Interpreter Shortcuts

Depending on your system, you may be able to scroll through an editable history of previous lines you've typed by using the up- and down-arrow keys on your keyboard.

On Windows XP and Windows 2000, this history feature is handled by the cmd shell. On Windows 95, 98, and Me, it is handled by the doskey utility (if it's running). On Unix-like systems, it's handled by the GNU Readline and History libraries, if they were linked to when your copy of Lua was compiled.

Here's another typing saver. When the interpreter sees a line that starts with =, such as the following, it treats the rest of the line as though it came between the parentheses of a print:

> =2 + 2

4

This is not part of the Lua language proper—it only works when you're typing something into the interpreter interactively. This means it's not to be confused with the use of the equal sign that is part of Lua proper, which you'll learn about in the next section. You can substitute this typing-saver use of = for print() in some of the examples in this chapter, but not all of them. Roughly speaking, you can only use it if what you're typing is a line unto itself, and not part of one of the multiline structures you'll learn about later. For consistency, this book generally uses print(), but you should substitute = when possible.

If you can access the history of what you've typed with the arrow keys, you may (depending on your system) see that lines that start with = have been transformed into lines that start with return. You'll learn about return in the next chapter.

Numerical Gotchas

At the intersection of the elegant world of mathematics and the sometimes rough-and-ready world of computers, nonintuitive things may happen. This section explains the major ones.

Division by Zero and Overflow

In arithmetic, dividing a number by zero is undefined. It's also undefined in Lua, which in practice means that what happens when you divide by zero depends on the C compiler used to compile your copy of Lua. To find out what happens on your own system, simply divide something by zero and observe the result. Here is an incomplete list of the possibilities:

· Lua may abruptly exit (with no error message).

· Lua may freeze and your operating system may display an error message. (If necessary, use Ctrl+C to get out of Lua.)

· The calculation may succeed and give a result. This result may not be a regular number but may instead look like -1.#IND, 1.#INF, Inf, or NaN.

If you do get a pseudo-number like NaN, beware: These generally have unusual behavior, sometimes to the extent of not being equal to themselves.

Unless you're prepared for the results, never divide by zero.

On most systems, the highest and lowest possible numbers have more than 300 digits (when written in regular base-10 notation). If you happen to go beyond these limits, the same division-by-zero warnings discussed in this section apply.

Floating-Point Rounding

Decimal-point notation cannot accurately express fractions unless they can be expressed in tenths, hundredths, and so on. For instance, ½ is frac510 or 0.5; ¼ is frac25100 or 0.25; but frac13 is somewhere between 0.33333333 and 0.33333334. Most computer hardware stores numbers in base-2 format, which has a similar problem—numbers not expressible as halves, quarters, eighths, and so on must be rounded to the nearest such fraction before they can be stored. This means that even a seemingly simple number like 0.1 cannot be accurately represented.

Another type of rounding takes place when a number is printed—if it would have an absurdly long number of decimal places, it is rounded to a nearby number. The following example demonstrates both types of rounding:

This example uses some things you won't learn until later in this chapter. It's shown here for reference purposes only.

> AlmostOne = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 +

>> 0.1 + 0.1 + 0.1 + 0.1 + 0.1

> print(AlmostOne < 1)

true

> print(AlmostOne)

1

Don't let this scare you off—in most situations problems like this don't arise. However, if you do run into two numbers that look alike but are not equal to each other, you now know a possible cause.

If you want to know more about these issues, go to the library or the web. One standard reference is David Goldberg's paper “What Every Computer Scientist Should Know About Floating-Point Arithmetic,” which is available at http://docs.sun.com/source/806-3568/ncg_goldberg.html.

By default, Lua uses what are known as double-precision floating-point numbers. It's possible to recompile Lua to use another representation for numbers. Unless you're using special hardware, doing this will not avoid the problems just discussed (or it will trade them for another set of problems).

Variables and Assignment

Like almost all programming languages, Lua has variables. For now, you can think of these as named cubbyholes or storage containers for values. (Numbers are the only values you've encountered so far, but you'll learn about other types later in the chapter.) After you put a value into a variable, you can refer to it using the variable's name.

Assignment Basics

Putting a value into a variable is called assignment. Here are two examples of assignment (along with some prints that show what's going on):

> NumberA = 2

> print(NumberA)

2

> NumberB = 2 + 2

> print(NumberB)

4

> print(NumberA + NumberB)

6

An equal sign assigns a value to a variable. In these examples, the value 2 is assigned to the variable NumberA, and the value 4 (the result of 2 + 2) is assigned to the variable NumberB.

After a value has been assigned to a variable, you can access the value again using the variable's name, such as print(NumberA) or print(NumberA + NumberB) .

Notice that Lua's equal sign means a different thing than the one in algebra. The algebraic equal sign is a statement of fact indicating that two things are equal. Lua's equal sign is a command to Lua to make two things equal, so that the one on the left can be used in place of the one on the right. Because of this, a particular variable may contain different values at different points in a program. Here's an example:

> Sum = 2 + 2

> print(Sum)

4

> Sum = 2 + 5000

> print(Sum)

5002

There are rules for variable names, or identifiers: An identifier has to start with a letter or an underscore. It can't contain anything other than letters, underscores, or digits. Nor can it be one of Lua's reserved words or keywords, which are and, break, do, else, elseif, end, false, for, function, if, in, local, nil, not, or, repeat, return, then, true, until, and while. The following are all valid identifiers:

· a

· A

· ABC

· _xyz

· something_55

· AnotherThing

· ____

None of the following are valid identifiers:

· function(a keyword)

· this-var(contains something other than a letter, number, or underscore)

· 1stThing(starts with something other than a letter or underscore)

Lua is case-sensitive, which means that NUM, Num, and num are all different identifiers:

> NUM = 1

> Num = 2

> num = 3

> print(NUM)

1

> print(Num)

2

> print(num)

3

This also means that FUNCTION, Function, and fUnCtIoN are all valid identifiers, because none of them is the keyword function.

There are various styles for identifiers:

· totalsales

· total_sales

· totalSales

· TotalSales

Some programmers even use different styles for different types of variables. If you're working on someone else's code, use the style used by that code. In your own code, pick a style and stick to it. This book uses the style TotalSales. Lua itself generally uses the totalsales style, so in this book, you can tell by looking whether a variable is defined in an example or built into Lua.

Lua has a few special variables that start with an underscore followed by capital letters (and possibly a number), such as _G or _PROMPT2. Avoid using names like that so that your variables don't clash with them.

A single underscore (_) is often used as a variable for junk values—values that need to be assigned, but won't be used. (You see this in Chapter 4 and elsewhere in the book.)

Multiple Assignment

You can assign multiple values to multiple variables at the same time. You can also print multiple values at the same time. The comma is used for both. Here's how you use the comma for multiple assignment, and for printing multiple values at the same time:

> Sum, Product, Exponent = 10 + 10, 10 * 10, 10 ^ 10

> print(Sum, Product, Exponent)

20 100 10000000000

In this example, three values were generated by adding 10 to itself, multiplying it by itself, and raising it to the 10th power. These three values were assigned respectively to the three variables Sum, Product, and Exponent. These three variables (more specifically, the values in these variables) were then printed.

You can also use multiple assignment to swap, rotate, or otherwise interchange the contents of variables. Here's an example:

> A, B = 1, 2

> print(A, B)

1 2

> A, B = B, A

> print(A, B)

2 1

> John, Jane, Jolene = "chips", "lemonade", "egg salad"

> print(John, Jane, Jolene)

chips lemonade egg salad

> John, Jane, Jolene = Jane, Jolene, John

> print(John, Jane, Jolene)

lemonade egg salad chips

Notice that without multiple assignment, swapping the contents of two variables would require a third variable for temporary storage:

>A = 1

> B = 2

> print(A,B)

1 2

> Tmp = A

> A = B

> B = Tmp

> print(A,B)

2 1

Variables on the Right Side of Assignments

As you may have noticed in some the previous examples, and as shown in the following example, the thing to the right of the equal sign can also be a variable:

> A = 10

> B = A

> print(B)

10

Even if a variable got its value from another variable, the two variables are independent. For example:

> A = 10

> B = A

> print(A,B)

10 10

> A = 555

> print(A,B)

555 10

This is because once the assignment gets the value of a variable that's on its right side, it forgets what variable the value came from (or even that it came from a variable at all).

Strings

Numbers are nice, but most programs need to deal with strings, which are sequences of characters (a letter, digit, space, or punctuation mark) or control characters (such a newline or formfeed).

Quoting Strings

A string can contain any text—even something that itself looks like Lua code—so it needs to be separated from the actual Lua code that comes before and after it. This is called quoting the string.

There are three ways to quote strings: with double quotes, with single quotes, and with square brackets.

Quoting Strings with Double Quotes

The double quote characters (“) mark the beginning and end of the string. Marking the beginning and end is all they do; they are not actually part of the string, which is why print doesn't print them, as in this example:

> print("This is a string!")

This is a string!

Like numbers, strings are values, which means they can be assigned to variables. Here's an example:

> Name, Phone = "Jane X. Doe", "248-555-5898"

> print(Name, Phone)

Jane X. Doe 248-555-5898

The same variable can contain both a string and a number at different times, as shown here:

> Var = 42

> print(Var)

42

> Var = "forty-two"

> print(Var)

forty-two

You can also have an empty string, which contains no characters between the quote marks. For example:

> print("")

>

Quoting Strings with Single Quotes

You can also quote strings by using the single quote (or apostrophe) character (‘), like this:

> print('This is also a string.')

This is also a string.

Single quotes work exactly like double quotes except that a single-quoted string can contain a double quote (without that double quote marking the end of the string). Similarly, a double-quoted string can contain a single quote (without that single quote marking the end of the string). Here are some examples:

> print('Cry "Havoc," and let slip the dogs of war')

Cry "Havoc," and let slip the dogs of war

> print("Cry 'Havoc,' and let slip the dogs of war")

Cry 'Havoc,' and let slip the dogs of war

Other than how they treat embedded double and single quotes, single and double quotes work exactly the same, and you can use either one. The best practice is to pick one and stick with it in all cases except those in which the other is more convenient.

Quoting Strings with Square Brackets

You can also quote strings with pairs of square brackets. Square brackets are used mainly for strings that would be too unwieldy to quote with double or single quotes, like this one:

> print([[There are some

>> funky "\' characters

>> in this string.]])

There are some

funky "\' characters

in this string.

If you mark the beginning of a string with two open square brackets ([[), then you mark the end with two close square brackets (]]). Inside such a string, no characters have any special meaning—a double quote represents a double quote, a newline (the invisible character that marks the end of a line, as when you press Enter) represents a newline, a backslash represents a backslash, a backslash followed by a letter n represents a backslash followed by a letter n, and so on. Strings quoted this way are sometimes called long strings, because they can be spread out over several lines, but they work fine on one line too.

If the first character of a square-bracket string is a newline, it is ignored. This allows you to write multiline square-bracket strings in an easier-to-read way. The following two prints print exactly the same thing, but the second looks more like its result:

> print([[ +-----+

>> | Lua |

>> +----- +

>> ]])

+----- +

| Lua |

+----- +

> print([[

>> +----- +

>> | Lua |

>> +----- +

>> ]])

+----- +

| Lua |

+-----+

What if you wanted to print two close square brackets inside a long string? For example:

> print([[Here ]] are some square brackets.]])

stdin:1: ')' expected near 'are'

The square brackets are interpreted by Lua as the end of the string. A backslash (the Lua escape character, discussed in the following section) won't prevent this from happening, because backslashes have no special meaning inside square-bracket strings. Instead, put an equal sign between the string's opening square brackets, and another between the closing square brackets:

> print([=[Here ]] are some square brackets.]=])

Here ]] are some square brackets.

If you need to, you can use multiple equal signs—the same number at the beginning and the end—like this:

> print([=[babble ]=] burble]=])

stdin:1: ')' expected near 'burble'

> print([==[babble ]=] burble]==])

babble ]=] burble

> print([====[babble ]=]==]===] burble]====])

babble ]=]==]===] burble

In other words, a square-bracket string starts with an open square bracket, zero or more equal signs, and another open square bracket, and it ends with a close square bracket, the same number of equal signs, and another close square bracket.

Lua 5.0 had a slightly different quoting method for long strings: The beginning was always [[ (never [=[ or [==[), and the end was always ]] (never ]=] or ]==] ). Also, matching sets of bracket pairs could nest—[[[[ ]]]] was legal and equivalent to “[[ ]]”. The equivalent Lua 5.1 long string would be[=[[[ ]]]=] .

Backslash Escaping

You can use the backslash character (\)inside double- and single-quoted strings to do things that would otherwise be inconvenient or impossible.

When the double quote character occurs within a double-quoted string, it has a special meaning: end of string. As you saw earlier, one way to avoid this special meaning (so that a double quote can be part of a string) is to quote the string with single quotes. Here's another way, using the backslash:

> print("Cry \"Havoc\"")

Cry "Havoc"

When a double quote is preceded by a backslash, the double quote's end-of-string meaning is taken away (escaped), and it becomes a part of the string. The backslash itself is not part of the string (in the same way that the quotes at the beginning and end of the string aren't part of it).

In other words, a backslash followed by a double quote represents a double quote. In the same way, a backslash followed by a single quote represents a single quote. For example:

> print('Ain\'t nobody\'s business if you do!')

Ain't nobody's business if you do!

A backslash followed by a backslash represents a backslash (just one):

> print("1 backslash: \\ 2: \\\\ 3: \\\\\\")

1 backslash: \ 2: \\ 3: \\\

And a backslash followed by a newline represents a newline:

> print("one\

>> two")

one

two

Different systems have different conventions for what character or character sequence is used to mark the end of a line. Lua accounts for this automatically—if any of the common end-of-line characters or character sequences occur in Lua code, inside or outside of string quotes, they are silently translated to newlines.

Normally, breaking a string into two lines would result in an error such as this:

> print("one

>> two")

stdin:1: unfinished string near '"one'

In addition to letting double quotes, single quotes, backslashes, and newlines represent themselves, the backslash also gives special meanings to some characters. For example, a backslash followed by a lowercase letter n represents a newline:

> print("one\ntwo")

one

two

These sequences of characters that start with a backslash are called escape sequences, because they temporarily escape from the normal interpretation of characters. Here are all of them:

2-1

A backslash followed by one, two, or three decimal digits represents the character whose numeric representation (inside the computer's memory or on a disk) is that number. This varies from system to system, but on most systems "\99" is the same as "c" —of course, in most circumstances it would make more sense to use the latter form rather than the former.

Lua's escape sequences are similar to those of the C language. The most important difference is that numeric escapes like \123 are interpreted as decimal (base 10), not octal (base 8).

Lua strings can include any character, including the null byte: the (invisible) character whose numeric representation is 0. However, parts of Lua that depend on the C language to handle strings will consider that character to mark the end of the string. For example:

> EmbeddedNull = "BEFORE\0after"

> print(EmbeddedNull)

BEFORE

Relational Operators and Boolean Values

+, -, *, /, and ^ are called operators, or more specifically, arithmetic operators. Arithmetic operators ask “how much” questions. In this section you learn about relational operators, which ask yes-or-no questions.

Comparing Numbers

The operators in this section are relational because they ask about the relation between two values: whether one value is less than the other, greater than it, equal to it, and so on.

Here's how to ask Lua whether one number is less than another:

> print(4 < 5)

true

> print(5 < 4)

false

You've learned about two types of values so far: numbers and strings. The less-than operator always gives true or false as a result. true and false look like strings at first glance, but actually they are a new type, called Boolean values (named after the 19th-century mathematician George Boole). There are lots of numbers (1, -300, 3.14159) and lots of strings ("Hello there!", "apple", "asdfjkl;"), but true and false are the only Booleans. Because they are values, they can be assigned to variables. To hard-code a Boolean value into a program, just type true or false (with no quotes), like this:

> Boolean1, Boolean2, Boolean3 = true, false, 1 < 2

> print(Boolean1, Boolean2, Boolean3)

true false true

There are six relational operators:

· A < B Is A less than B?

· A > B Is A greater than B?

· A <= BIs A less than or equal to B?

· A >= BIs A greater than or equal to B?

· A == BIs A equal to B?

· A ~= B Is A not equal to B?

Of these six, <, >, <=, and >= determine what order two values are in. == and ~= just determine whether two values are equal. For example:

> print(1 > 1)

false

> print(1 > 2)

false

> print(1 >= 1)

true

> print(1 >= 2)

false

> print(1 == 1)

true

> print(1 == 2)

false

> print(1 ~= 1)

false

> print(1 ~= 2)

true

Two values of different types are never considered equal, even if they look similar. So the number 1 is not equal to the string "1" , and the string "true" is not equal to the Boolean true. Also, unlike some other languages, the number 0 is not equal to either the empty string ““ or the Boolean false, and the number 1 is not equal to the Boolean true.

Here are a couple common errors:

> Num == 42

stdin:1: '=' expected near '=='

> print(Num = 42)

stdin:1: ')' expected near '='

A single equal sign is used for assignment and a double equal sign is used for equality comparison. It's very common to mix these up, but Lua always spots the error.

Comparing Strings

If two strings have the same characters in them (in the same order), then they are considered the same string, which means they are equal to each other (because a value is always equal to itself). For example:

> Str1 = "Jane X. Doe"

> Str2 = "Jane X. Doe"

> print(Str1 == Str2)

true

<, >, <=, and >= can be used on strings as well. Single-character strings compare based on their collation (sorting) order in the current locale. In the simplest case, this is their order in your system's character set. (Locale is a system setting that determines, among other things, the appropriate alphabetization order for the language being used.) Here are some examples:

> print("a"<"b")

true

> print("a" < "a")

false

> print("a" <= "a")

true

> print("A" < "a")

true

> print(" " > "\n")

true

Multiple-character strings compare based on the first character that is different, like this:

> print("abcd" < "abce")

true

The absence of a character is considered less than any character, as these examples illustrate:

> print("" < "A")

true

> print("" < "\0")

true

> print("abc" < "abcd")

true

Although == and ~= can be used with values of any type, even values of two different types, the <, >, <=, and >= operators can only be used with two numbers or two strings. Anything else causes an error, as these examples show:

> print(false < true)

stdin:1: attempt to compare two boolean values

stack traceback:

stdin:1: in main chunk

[C]: ?

> print(42 >= "41")

stdin:1: attempt to compare string with number

stack traceback:

stdin:1: in main chunk

[C]: ?

The rule that < ,> ,<= , and>= can only be used to compare two strings or two numbers is not strictly true. You'll learn how to bypass this rule—and several other rules given in this chapter—with metata-bles in Chapter 8.

The nil Value

Assigning an initial value to a variable is called initializing it. A variable that has had no value assigned to it is said to be uninitialized. You've learned about three types of value (also known as datatypes) so far: numbers, strings, and Booleans. There's one more type to learn about in this chapter, and you'll see it if you print the value of an uninitialized variable such as the following:

> print(Asdf)

nil

This is the value nil. Its type is also named nil; in fact it is the only value whose type is nil. It is used mainly to represent the absence of any other value. Any uninitialized variable has nil as its value.

You can also explicitly assign nil to a variable, which you might do if you want Lua to forget about the variable's previous value. For example:

> Password = "$xa(yb 'y'

> print(Password)

$xa(yb 'y

> Password = nil

> print(Password)

nil

nil also comes into play when an assignment is made that has more variables on its left side than values on its right side. Here's an example:

> C, D = 3, 4

> A, B, C, D = 1, 2

> print(A, B, C, D)

1 2 nil nil

If there are more variables on the left side of an assignment than there are values on the right side, the list of values is adjusted to the correct length by adding nils to the end. So the line where A and B are assigned as follows:

> A, B, C, D = 1, 2

acts just as though it had been written like this:

> A, B, C, D = 1, 2, nil, nil

This means that extra variables (C and D in this example) are set to nil , even if they already have been set to another value.

If there are more values on the right than variables on the left, the list of values is adjusted by throwing away the extra values, like this:

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

> print(A, B)

1 2

nil is different from false, 0, and the string "nil". But, like all values, it's equal to itself:

> print(nil ~= false)

true

> print(nil ~= 0)

true

> print(nil ~= "nil")

true

> print(nil == nil)

true

If a nil turns up where you don't expect it, a typo is usually the cause. In the following example, the variable LoginCount is initialized, but then its name is miscapitalized as LoglnCount, which is a different variable:

> MaxLoginCount = 100

> LoginCount = 50

> print(LogInCount > MaxLoginCount)

stdin:1: attempt to compare number with nil

stack traceback:

stdin:1: in main chunk

[C]: ?

Because LoginCount is uninitialized, its value is nil, which can't be compared to a number.

In the next example, Joe and Mike were intended as strings, but because they are not quoted, they're treated as (uninitialized) variables:

> FirstNameA, FirstNameB = Joe, Mike

> print(FirstNameA < FirstNameB)

stdin:1: attempt to compare two nil values

stack traceback:

stdin:1: in main chunk

[C]: ?

Boolean Operators

The three Boolean operators —and, or, and not —are handy for working with Boolean values. However, as you will see, they can also be given non-Boolean values, and two of them (and and or) don't always even give Boolean results.

The and Operator

Like the other operators you've seen so far, the and operator takes two values, one to its left and one to its right. The values given to an operator are called operands. The simple explanation of and is that it gives a true result only if both of its operands are true, as follows:

> print(false and false)

false

> print(false and true)

false

> print(true and false)

false

> print(true and true)

true

One way that you can use this is to check if a number is within a range. In the following example Num > 10 is true and Num < 20 is true, so the result is true:

> Num = 15

> print(Num > 10 and Num < 20)

true

If you use operands that aren't Booleans, the behavior of and is a bit more subtle. Here are some examples—see if you can figure out what rules and is following in them:

> print(false and nil)

false

> print(nil and false)

nil

> print(false and 1)

false

> print(1 and false)

false

> print(nil and 1)

nil

> print(1 and nil)

nil

> print(nil and true)

nil

> print(true and nil)

nil

> print(true and 1)

1

> print(1 and true)

true

> print("a" and 1)

1

> print(1 and "a")

a

The more complicated explanation of the and operator is that if its first operand is false or nil, then the first operand is used as the result; otherwise the second operand is used as the result. Mentally apply that rule to the preceding examples to see if you come up with the same answer as Lua.

Notice that the complicated explanation is the same as the simple explanation if you consider both false and nil to be false values and everything else to be true values. There's a distinction here between true and false, which are proper names for specific values in Lua, and "true" and "false," which are adjectives. In this book, the adjectives will always be in the same typeface as the surrounding text, and the names will be in this typeface, like so:

false and nil are false. true and "Jane Doe" are true.

Remember, false and nil are the two false values, and every other value is a true value. This means that, unlike some other languages, the number 0 and the empty string are both true.

The or Operator

The or operator gives a false result only if both its operands are false, as follows:

> print(false or false)

false

> print(false or true)

true

> print(true or false)

true

> print(true or true)

true

Like and, the result of or is always one of its operands. If its first operand is something other than false or nil, then the first operand is used as the result; otherwise the second operand is used as the result. For example:

> print(42 or nil)

42

> print(nil or 42)

42

> print(false or nil)

nil

> print(nil or false)

false

> print("first" or "second")

first

> print(false or "second")

second

This behavior comes in handy in the following example.

> print(FavoriteFruit or"apple")

apple

> FavoriteFruit = "kiwi"

> print(FavoriteFruit or"apple")

kiwi

The print line (which occurs twice in the example) is the interesting one here. If there's a favorite fruit, that line prints it. If, however, FavoriteFruit is uninitialized (and therefore is nil), there's no favorite fruit, and the default ("apple") is printed.

There can be chains of these, in which case, the result is the first value that is true. Here's an example:

> Choice1, Choice2, Choice3 = nil, "pencil", "pen"

> print(Choice1 or Choice2 or Choice3)

pencil

Mathematicians consider the or operator to be the Boolean equivalent of addition, and the and operator to be the Boolean equivalent of multiplication.

The not Unary Operator

Most of the operators you've learned about so far are binary; that is, they take two operands, one to the left of the operator and one to the right. (This meaning of binary is not to be confused with the base-two number system.) You've seen one unary (a one-operand) operator as well, although you may not have realized it. It's the so-called unary minus, and you've already used it to make negative numbers, like this:

> print(-50)

-50

> print(-2 + -2)

-4

You can also use it to make any positive value negative, or make a negative value positive. :

> Two = 2

> print(-Two)

-2

> MinusTwo = -Two

> print(-MinusTwo)

2

- is both a binary and a unary operator, but Lua never gets these two uses confused, because it's always visible from the context which one you intended:

> print(-13 - -2)

-11

and and or are both binary, but the remaining Boolean operator, not, is unary. As with -, the not operand goes to its right. If that operand is false or nil, then the result of not is true; otherwise, it's false:

> print(not false)

true

> print(not nil)

true

> print(not true)

false

> print(not 50)

false

> print(not "Hello")

false

If a true value is preceded by two nots, the result is true; if a false value (that is, false or nil) is preceded by two nots, the result is false:

> print(not not true)

true

> print(not not 50)

true

> print(not not "Hello")

true

> print(not not false)

false

> print(not not nil)

false

The Concatenation, Length, and Modulo Operators

There are three other operators you need to know about: concatenation, length, and modulo. You'll examine all three in the following sections.

The String Concatenation Operator

The string concatenation operator is written like this: .. (two periods, with no spaces between them). It takes two strings as operands and concatenates them, or splices them together. Here are some examples:

> print("App" .. "le")

Apple

> print("a" .. "b" .. "c" .. "d")

abcd

> Name = "dear reader"

> print("Hello, " .. Name .. ", how are you?")

Hello, dear reader, how are you?

The .. operator creates a new string by putting its two operands together with no space between them. If you want a space (or some other separator), explicitly include it in the concatenation, like this:

> print("Jane" .. "Doe")

JaneDoe

> print("Jane" .. " " .. "Doe")

Jane Doe

As mentioned previously, two strings with the same characters in the same order are the same string. This means that two different concatenations can have equal results. For example:

> OneAndTwoThree, OneTwoAndThree = "1" .. "23", "12" .. "3"

> print(OneAndTwoThree, OneTwoAndThree)

123 123

> print(OneAndTwoThree == OneTwoAndThree)

true

Concatenating a string to the empty string gives the same string:

> print("abcd" .. "" == "abcd")

true

The Length Operator

The length operator #, like not and one version of -, is a unary operator. It measures the length of a string. (It also measures the length of a table, which you'll learn about in Chapter 4.) Take a look at these—examples:

> print(#"")

0

> print(#"!")

1

> print(#"\n")

1

> print(#"abcd")

4

> VerbForms = "see saw seen"

> print(#VerbForms)

12

The length of a string is simply the number of characters in it. (Notice that "\n" is a single character, even though it is typed as two.)

Lua considers a character to be exactly one byte—a small chunk of memory just big enough to be able to take on one of 256 different values. (To be pedantic, Lua considers a character a C char, but that will be one byte on any system you're likely to use.) This makes a difference if you're using a character encoding (UTF-8, for example) in which some characters take up more than one byte; the following word looks like it's four characters long, but Lua sees it as five:

> print(#"fi_o")

5

Lua counts the null byte just like any other character:

> NullByte = "\0"

> NullBytes = NullByte .. NullByte .. NullByte

> print(#NullByte)

1

> print(#NullBytes)

3

> print(#"before\0between\0behind")

21

Lua 5.0 didn't have the length operator #. To get the length of a string, use the function string.len; to get the length of a table, use the function table.getn.

The Modulo Operator

Imagine the hour hand of a clock. If it's pointed at 3 and you turn it two hours forward, it's now pointed at 5. This can be modeled by addition: 3 plus 2 equals 5. But what if, when it's pointed at 5, you turn it—144 hours forward? The answer is that it will still be pointed at 5 because 144 is divisible by 12. After the—hour hand passes 12, the addition model breaks down (in this case giving the answer 149). The modulo operator, %, is good for modeling cyclical things like hours in a day, days in a week, or musical pitches in an octave.

Try It Out

Using % to Model a Clock Face

The following example models setting an hour hand to 3, moving it two hours forward, moving it 144 hours forward, and moving it 149 hours backward. For this example, pretend that the top of the clock says 0 instead of 12 (the fact that real clocks go from 1 to 12 rather than 0 to 11 could be adjusted for by adding and subtracting 1 at the appropriate points, but that would needlessly complicate this example).

>Hour = 3

>Hour = Hour + 2

>Hour = Hour % 12

> print(Hour)

5

> Hour = Hour + 144

> Hour = Hour % 12

> print(Hour)

5

> Hour = Hour - 149

> Hour = Hour % 12

> print(Hour)

0

How It Works

The lines where addition or subtraction is done represent turning the hour hand, but they can leave Hour either too high (greater than or equal to 12) or too low (negative). The lines where % is used adjust for this. Hour % 12 is pronounced “hour modulo twelve” or “hour mod twelve,” and it means “What would Hour be if I added or subtracted enough 12s so that it was less than 12 and greater than or equal to zero?”

For positive numbers (even fractional ones), this is the same as the remainder of a division. For example, 35 % 12 is 11 because 12 goes into 35 two times with a remainder of 11. This can be used to check whether a number is divisible by another number. For instance, if X is even, then X % 2 will be 0.

In other languages, the modulo operators and functions treat negative numbers differently than the Lua % operator does. The Lua operator follows the definition of modulo most commonly used by mathematicians. One way of stating this definition is as follows:

To find X % Y add Y to (or subtract it from) X as many times as necessary until a number between 0 and Y is reached. (This number can be exactly equal to 0, but it cannot be exactly equal to Y.)

This definition allows the clock-face example to work even when Hour briefly becomes negative.

As with division by zero, using zero as the second operand of % is undefined.

Lua 5.0 didn't have the % operator. Use the function math.mod instead, but be warned that it has different behavior with negative numbers.

Automatic Conversion of Operands

Some operators (such as ==) can take operands of any type. Other operators (such as <) expect operands of a certain type and produce an error message if given the wrong type. The arithmetical operators (+, -, *, /, ^, and %) fall into this second category, except that they will attempt to convert string operands into numbers, like this:

> print("2" + "2")

4

The result is still a number, not a string. If the conversion attempt fails, an error message like the following results:

> print("x" + "y")

stdin:1: attempt to perform arithmetic on a string value

stack traceback:

stdin:1: in main chunk

[C]: ?

If the string is a hexadecimal number, it must be positive. (Negative hexadecimal numbers may be converted correctly, but this is not guaranteed—it depends on the C library used to compile Lua.)

The string concatenation operator also does an automatic conversion, from number to string. For example:

> print(111 .. 999)

111999

Precedence and Associativity

You may remember from math class that both 5 * 5 + 1 and 1 + 5 * 5 give the same result—multiplication is done before addition even if it comes later. Multiplication is therefore said to have a higher precedence than addition. However, if you want to do a lower-precedence operation before a higher-precedence one, you can surround the lower-precedence one in parentheses.

The following shows that, no matter what the left-to-right order, multiplication will always be done before addition, unless the addition is wrapped in parentheses, in which case it will be done first:

> print(5 * 5 + 1)

26

> print(1 + 5 * 5)

26

> print(5 * (5+ 1))

30

> print((1 + 5) * 5)

30

Notice that parentheses are being put to two different uses here—to override precedence and to wrap the thing being printed. These two uses are completely unrelated, but in both cases each open parenthesis must have a corresponding close parenthesis. If the open and close parentheses don't match up, you'll get either an error message or a continuation prompt telling you to finish what you started:

> print((1 + 5) * 5))

stdin:1: unexpected symbol near ')'

> print(5 * (5 + 1)

>>

What about two operators that have the same precedence? In some cases, it doesn't matter what order they're done in: (2 + 3) + 4 and 2 + (3 + 4) are both 9. But how about 2 - 3 + 4? This will give a different answer depending on whether the subtraction or the addition is done first, and precedence can't be used to decide this because addition and subtraction have the same precedence. In this case, the subtraction is done first because it's on the left, and + and - are both left-associative operators. Anytime two operators are the same precedence, they are done from left to right if they're left associative, and right to left if they're right associative. Lua only has two right-associative operators: .. (string concatenation) and ^ (exponentiation). (That's not counting unary operators, which are done from right to left because that's the only way that makes sense.)

The following chart lists all of Lua's operators, from highest precedence to lowest. (All operators are binary unless marked as unary, and all binary operators are left associative unless marked as right associative.)

^ (exponentiation; right-associative)

not (Boolean negation; unary), - (unary minus), # (length; unary)

* (multiplication), / (division), % (modulo)

+ (addition), - (subtraction)

.. (string concatenation; right-associative)

< (less than), > (greater than), ~= (not equal to), <= (less than or equal to), == (equal to), >= (greater than or equal to)

and (Boolean"multiplication")

or (Boolean "addition")

Most experienced programmers do not memorize this whole chart, nor do they check it every time they can't remember a precedence. Rather, they memorize a handful of the most commonly used precedences and use parentheses for anything they're not sure of. It doesn't hurt to add parentheses even if they're not strictly necessary according to the precedence chart, and it often makes your code easier for you and others to understand.

On the other hand, Lua's precedence chart is well thought out, and many common idioms do not require parentheses. For example, relational operators have comparatively low precedence, which means that arithmetic results don't need to be wrapped in parentheses before being compared:

> CreditA, DebitA, CreditB, DebitB = 1000, 150, 500, 25

> print(CreditA - DebitA == CreditB - DebitB)

false

> print(CreditA - DebitA > CreditB - DebitB)

true

and and or both have very low precedence, so you don't need to wrap comparisons in parentheses before using and or or:

> CreditA, DebitA, CreditB, DebitB = 1000, 150, 500, 505

> print(CreditA >= DebitA and CreditB >= DebitB)

false

> print(CreditA >= DebitA or CreditB >= DebitB)

true

and has higher precedence than or, so you can use A and B or C to mean “if A, then B, otherwise C.”

Here's the A and B or C trick in action:

> B, C = "B was chosen", "C was chosen"

> A = true

> print(A and B or C)

B was chosen

> A = false

> print(A and B or C)

C was chosen

A is anded with B and the result (A if A is false, otherwise B) is ored with C. The upshot is that whether A is true or false determines whether the result is B or C. This would have worked the same if A had been set to any true value instead of true, or nil instead of false. It would not have worked, though, if B had been nil or false:

> B, C = false, "C was chosen"

> A = true

> print(A and B or C)

C was chosen

This is a limitation of this idiom—the middle value must be true.

Variables and Values

Earlier you read that variables are like named cubbyholes or containers for values. This means that the following assignment finds the three cubbyholes Number, Greeting1, and Greeting2 (creating them if they don't already exist) and puts 123 in Number, "Hello" in Greeting1, and "Hello" in Greeting2:

Number, Greeting1, Greeting2 = 123, "Hello", "Hello"

This is illustrated in Figure 2-1.

2-1

Figure 2-1

For everything you've done and will do in this chapter, that's a perfectly accurate mental model, but later you'll run into situations where it would lead you astray. Before you get it too ingrained in your head, a somewhat more accurate model is that the following finds the three names Number, Greeting1, and Greeting2 (creating them if they don't already exist) and points Number's arrow at 123 and Greeting1's and Greeting2's arrows at "Hello":

Number, Greeting1, Greeting2 = 123, "Hello", "Hello"

This is illustrated in Figure 2-2.

2-2

Figure 2-2

The difference is that instead of Greeting1 and Greeting2 each containing "Hello", they only point to it. Chapter 4 explains why this is important.

Comments

If Lua sees two consecutive hyphens outside of a string, it considers everything until the end of that line a comment and ignores it. For example:

> print("Hello") -- This is a comment.

Hello

> print("Goodbye") -- So is this.

Goodbye

Comments are useful to explain your code's purpose to other programmers (or to remind yourself when you return to the code after a few months). Whenever you change your code, make certain you update your comments appropriately.

Comments can also be used to temporarily comment out code that you want Lua to ignore but don't want to delete entirely, like this:

> -- print("Hello")

>

If the two hyphens are immediately followed by an open square bracket, zero or more equal signs, and another open square bracket, then Lua uses the rules described previously for long strings (square bracket strings) to ignore the following text (including the rule about nested sets of square brackets needing different numbers of equal signs). This is most often used for multiline comments such as the following:

> --[[ This is

>> a multi-line

>> comment.]]

>

It can also be used to temporarily comment out code in the middle of a line, like this:

> print(2 + --[[2 +]] 2)

4

Or to temporarily comment out multiple lines of code, like this:

> --[[

>> print("Multiple")

>> print("lines.")

>> --]]

>

Notice that the closing brackets have -- in front of them. This lets you add a single - in front of the opening brackets (turning that line into a single-line comment rather than the start of a multiline comment) without the closing brackets causing an error:

> --- [[

> print("Multiple")

Multiple

> print("lines.")

lines.

> --]]

>

That looks pretty silly typed into the interpreter, but you'll find it useful for debugging when you start saving code to (and executing it from) files.

Even though code typed directly into the interpreter is normally short-lived and not commented, much of the following example code is commented for your benefit.

Expressions and Statements

For most of this chapter, you've been using expressions and statements. For the rest of the chapter to make sense, these terms need to be defined.

An expression is something that has a value. As you've used print, you've been putting expressions (separated by commas when there is more than one) between its parentheses. An expression can be a literal value, such as a quoted string, true, false, or nil. Literalmeans that you can tell just by looking at it what it is. For example, a variable named Count may contain a number (and probably does, given its name), but it's not a literal number, like 42 is.

An expression can also be a variable name, like Count. It can also be an expression preceded by a unary operator, an expression wrapped in parentheses, or two expressions separated by a binary operator. For example, -Count is an expression because Count is an expression, and an expression preceded by a unary operator is also an expression. 2 + 3 is an expression because 2 and 3 are expressions, and separating two expressions with a binary operator makes another expression. Take a look at the following example:

Count > 5 and #(FirstNameStr .. LastNameStr) <= 20

Even a complicated expression like this can be explained as the literals 5 and 20 and the variable names Count, FirstNameStr, and LastNameStr combined according to the preceding rules.

There are other rules for making expressions, but these are the only ones relevant to this chapter.

A statement is the smallest complete unit of Lua code. A Lua program is simply one or more statements (actually zero or more, because if you enter an empty line into the interpreter, you're executing a valid program that does nothing). Lua doesn't know what to do with an expression unless it's wrapped in a statement such as the following:

> 2 + 2

stdin:1: unexpected symbol near '2'

> print(2 + 2)

4

As this example implies, print(...) is a statement. Assignment is also a statement, and these are the only two types of statement you've learned about so far in this chapter. You'll learn more in the next section.

For the most part, expressions and statements are two different things. There is one type of expression that can be used as a statement, and you'll learn about it next chapter.

Compound Statements

Compound statementsare statements that can contain other statements. The following sections describe five of Lua's compound statements: the if statement; the while, for, and repeat loops; and the do statement.

At any time during the execution of a program, a certain part of the program is in control. By default, control flows from each statement to the one after it, but most compound statements are control structures, so-named because they are structures (with multiple parts), and they alter the flow of control. The ifstatement is one of these control structures.

The if Statement

Say you have two strings, Str1 and Str2, and you want to concatenate them in (the < operator's version of) alphabetical order. To do so, you need to test whether Str1 comes before Str2 and, if it does, concatenate them with Str1 first, but otherwise concatenate them with Str2 first. You already know enough to do this, if you use the A and B or C trick described earlier. Give it a try.

You should come up with the following:

> Str1, Str2 = "aardvark", "zebra"

> print(Str1 < Str2 and Str1 .. Str2 or Str2 .. Str1)

aardvarkzebra

>

> Str1, Str2 = "zebra", "aardvark"

> print(Str1 < Str2 and Str1 .. Str2 or Str2 .. Str1)

aardvarkzebra

There's another way to do this, using the if control structure.

Try It Out

Using if to Make a Choice

The if version is a bit wordier but, at least in this case, it's easier to read, and it scales up more easily to more complicated things. Here's the code:

> Str1, Str2 = "aardvark", "zebra"

> if Str1 < Str2 then

>> print(Str1 .. Str2)

>> else

>> print(Str2 .. Str1)

>> end

aardvarkzebra

> -- Do it again with the strings swapped:

> Str1, Str2 = "zebra", "aardvark"

> if Str1 < Str2 then

>> print(Str1 .. Str2)

>> else

>> print(Str2 .. Str1)

>> end

aardvarkzebra

How It Works

In English: If the two strings are in the right order, then print them; otherwise, print them in reverse order.

The if control structure has the following form:

if an expression then

zero or more statements

else

zero or more statements

end

The expression is evaluated, that is, its value is checked. If the value is true (that is, something other than false or nil), then only the statements between the then and the else are executed; if the expression is false (that is, false or nil) then only the statements between the else and the end are executed.

An if statement doesn't have to be spread out across several lines. If it's not too long, you can fit it on one line. If you do spread it across several lines, indent the statements before and after the else, as the preceding example shows. Lua doesn't care about indentation, but humans find it much easier to read properly indented code.

If you have no statements to put in the else clause (the part between the else and the end), just leave the else out. For example:

if not Asdf then print("Asdf is false")end

if "X" .. "Y" .. "Z" == "XYZ" then

Name = "Virginia"

print("Yes, " .. Name .. ", it's \"XYZ\"")

end

it's possible to rewrite the alphabetical concatenation example with no else clause. Give it a try before you look at the following example. (Hint: the print statement needs to come after the end.)

> Str1, Str2 = "aardvark", "zebra"

> if Str1 > Str2 then

>> Str1, Str2 = Str2, Str1

>> end

> print(Str1 .. Str2)

aardvarkzebra

> -- Do it again with the strings swapped:

> Str1, Str2 = "zebra", "aardvark"

> if Str1 > Str2 then

>> Str1, Str2 = Str2, Str1

>> end

> print(Str1 .. Str2)

aardvarkzebra

In English: If the two strings are in the wrong order, swap them. Then print them (whether they were swapped or not).

This code does one thing if Str1 is greater than Str2 and does something else if Str1 is less than or equal to Str2. Similarly, the first version does one thing if Str1 is less than Str2 and something else if Str1 is greater than or equal to Str2. Because an if structure is a statement, it can be put inside a then clause or an else clause. This fact can be used to do one thing if Str1 is less than Str2, another thing if Str1 is greater than Str2, and yet another if they are equal. Write a version that concatenates Str1 and Str2 in order as before if they are inequal, but only prints one of them if they are equal. This means that the following:

Str1, Str2 = "aardvark", "aardvark"

should result in this:

aardvark

After you've written your code, test it and make sure it works. Testing it in this case means trying it out with all three cases: two strings in the right order, two strings in the wrong order, and two identical strings.

There are several correct ways to write this code. Here's one:

if Str1 == Str2 then

-- Str2 is a duplicate of Str1; replace it with the

-- empty string:

Str2 = ""

else

if Str1 > Str2 then

-- They're in the wrong order; swap 'em:

Str1, Str2 = Str2, Str1

end

end

print(Str1 .. Str2)

Because the inner if doesn't have an else, the strings are only executed if one of the two tests turns out true; if not, none of the statements except the final print is executed.

Notice that the contents of the outer if statement's then and else clauses are indented one level (which is two spaces in this book), and the inner if statement's then clause is indented one more level.

If an if statement is nested inside the else clause of another if statement, Lua allows them to be combined into one if statement using the keyword elseif.

Here's the nested-if version of alphabetical concatenation rewritten using elseif:

if Str1 == Str2 then

-- Str2 is a duplicate of Str1; replace it with the

-- empty string:

Str2 = ""

elseif Str1 > Str2 then

-- They're in the wrong order; swap 'em:

Str1, Str2 = Str2, Str1

end

print(Str1 .. Str2)

The elseif test (to see if the strings are in the wrong order) is only done if the if test (to see if the strings are equal) turned out false.

An if statement can have zero or more elseifs, and zero or one else. If there is an else, it has to be the last part of the if :

if N == 1 then

print("N is one")

elseif N == 2 then

print("N is two")

elseif N == 3 then

print("N is three")

else

print("N is neither one nor two nor three")

end

In an if like this, the test expressions (right before then) are evaluated from the first one downward, until the first true one is found, at which point the next statement block (the part between the then and the next elseif, else, or end) is executed, and the if is exited. The statement block after the else is only executed if none of the test expressions are true. In this example, you can tell at a glance that only one of the prints will be executed.

The while Loop

The if control structure gives a program the power to decide whether something gets executed. Lua's other control structures—while, repeat, and for—give a program the power to decide how many times something gets executed. They are called loops, and the simplest is while, whose form is as follows:

while an expression do

zero or more statements

end

The expression is evaluated. If it's true, the statements between do and end are executed, and then the expression is evaluated again. If it is still true, the statements are executed again, and the cycle continues. If the expression evaluates as false at any time (including the first time it's evaluated), thewhile statement is exited, which means that the statements are not executed and the expression is not evaluated again. For example, the following code does nothing:

while false do

print("This will")

print("never print.")

end

On the other hand, Here's an example that will run forever—(or until you stop it by pressing Ctrl+C):

while true do

print("It keeps")

print("going and going.")

end

More interesting cases are those where the expression starts out true, and then becomes false, like in the following example, which uses while to count to 10:

> Counter = 1

> while Counter <= 10 do

>> print(Counter)

>> Counter = Counter + 1

>>

end

1

2

3

4

5

6

7

8

9

10

>

Here, Counter is set to 1, and as long as it's less than or equal to 10, it is printed and then incremented (increased by one). At the end of the tenth time through the loop, Counter is set to 11. The test—whether Counter is less than or equal to 10—is done an eleventh time, this time with a false result, which means the loop is done.

A factorial is a number formed by multiplying a sequence of consecutive integers starting with 1. For example, the factorial of 5 (notated by mathematicians as “5!”) is 1×2×3×4×5, or 120. (Apart from their use in the mathematical field of combinatorics, factorials are quite handy for writing examples in programming books.)

The following code prints all the factorials less than 100:

> N, F = 1, 1

> while F < 100 do

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

>> N = N + 1

>> -- Compute the factorial of the new N based on

>> -- the factorial of the old N:

>> F = F * N

>> end

1! is 1

2! is 2

3! is 6

4! is 24

The first line initializes (gives initial values to) N and F, setting N to 1 and F to the factorial of 1, which also happens to be 1. The expression after while makes sure that F is less than 100. Inside the loop's body, N and F are printed, N is incremented, and the factorial of the new value of N is computed, using the fact that n! equals (n - 1) !×n.

The for Loop

One difference between the factorial loop and the 1-to-10 loop is that you knew the 1-to-10 loop's body would be executed 10 times, but you didn't know how many times the factorial loop's body would be executed (unless you figured the factorials out in your head). To know when to exit the loop, Lua had to compute 4!, see that it was less than 100, and then compute 5! and see that it was not less than 100. The while loop is for situations where you don't know how many times you want the loop to repeat. When you do know how many times you want the loop to repeat, use Lua'sfor loop. (It's called for because it does things for a certain number of times.)

Here's the 1-to-10 loop rewritten with for:

> for Counter = 1, 10 do

>> print(Counter)

>> end

1

2

3

4

5

6

7

8

9

10

Notice how much simpler it is than the first version. The for loop has the following form:

for variable = start number, end number, step do

zero or more statements

end

The value start number is assigned to variable, the zero or more statements are executed, step is added to variable (step is optional and usually left out, in which case 1 is used), and if variable is still less than or equal to end number, then the loop body is executed again.

If Lua sees that the variable will never either reach or go beyond end number, then the body is never executed:

> for N = 1, 0 do

>> print(N)

>> end

>

The right thing is done for negative and fractional values and cases where the difference between the start number and the end number is not divisible by the step value:

> for N = 3, 1, -1 do

>> print(N)

>> end

3

2

1

> for N = -50, -45.25, 2.5 do

>> print(N)

>> end

-50

-47.5

> for N = 2, 5, 2 do

>> print(N)

>> end

2

4

The start number, end number, and step value don't need to be, and often aren't, literal numbers—they can be any expressions that evaluate to numbers. This evaluation takes place once, at the beginning of the loop (unlike a while loop's test expression, which is evaluated over and over as the loop loops). That's why the following example loops five times, even though End gets lower and lower:

> End = 5

> for I = 1, End do

>> End = End - 1 -- The loop doesn't care that End is being

>> -- changed.

>> print("I is " ..I .. " and End is " .. End)

>> end

I is 1 and End is 4

I is 2 and End is 3

I is 3 and End is 2

I is 4 and End is 1

I is 5 and End is 0

for loops can be nested inside each other. For example:

> for Outer = 1, 3 do

>> for Inner = 1, 3 do

>> print("Outer: " ..Outer .." ; Inner: " ..Inner)

>> end

>> end

Outer: 1; Inner: 1

Outer: 1; Inner:2

Outer: 1; Inner:3

Outer: 2; Inner:1

Outer: 2; Inner:2

Outer: 2; Inner:3

Outer: 3; Inner:1

Outer: 3; Inner:2

Outer: 3; Inner:3

A common mistake is to forget the do after a for or while, or the then after an if or elseif. If you do this, you'll get an error message:

> for N = 1, 10

>> print(N)

stdin:2: 'do' expected near 'print'

Another way to say something loops is to say that it iterates. Looping in general is called iteration, but each time the body of a loop is executed is called an iteration.

On each iteration of a for loop, tHere's an implicit assignment to the loop variable (the variable named right after for). This variable has a behavior that you might not expect. In the following example, N is used both outside the loop and as a loop variable:

> N = "outside"

> for N = 1, 3 do

>> print(N)

>> end

1

2

3

> print(N)

outside

The outside value of N was unaffected by the numbers that were assigned to N inside the loop. A for loop's variable is only visible inside the loop—if you look at it outside the loop, you'll get any value it was given outside the loop (nil if it hasn't been given a value outside the loop). This is because the N inside the loop and the N outside the loop are actually two different variables—they're in two different scopes. (You learn more about this in the next chapter.)

The repeat Loop

The repeat loop is different in three ways from the while loop:

· Its expression is tested after its body (the statements between do and end), which means that the body is always executed at least once.

· The sense of the test is reversed—the while loop keeps going while the expression is true; the repeat loop, whose expression comes after the keyword until, keeps going until the expression is true.

· A repeat loop, unlike a while (or any other compound statement for that matter), does not end with the keyword end.

Here's the factorial example rewritten to use a repeat loop:

> N, F = 1, 1

> repeat

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

>> -- Compute the next N and its factorial:

>> N = N + 1

>> F = F * N

>> until F >= 100

1! is 1

2! is 2

3! is 6

4! is 24

THere's sort of an incipient bug in this version. It is that if you had wanted to see all factorials less than 1, then the while version would have given you the correct answer (none), but the repeat version would have incorrectly printed like this:

1! is 1

That's why you only use repeat when you know that you want the loop's body to be executed at least one time.

The repeat loop is the least commonly used control structure. There are a few examples of it in Chapter 18.

The break and do Statements

The break statement exits a while, for, or repeat loop prematurely. For example:

>for N = 1, 10 do

>> if N > 5 then

>> break

>> end

>> print(N)

>> end

1

2

3

4

5

>

If a break is inside more than one loop, it only breaks out of the innermost one as follows:

> for Outer = 1, 3 do

>> for Inner = 101, 103 do

>> print("Outer: " .. Outer .. "; Inner: " .. Inner)

>> if Inner == 102 then

>> print("Breaking out of inner loop; 103 won't be reached.")

>> break

>> end

>> end

>> end

Outer: 1; Inner: 101

Outer: 1; Inner: 102

Breaking out of inner loop; 103 won't be reached.

Outer: 2; Inner: 101

Outer: 2; Inner: 102

Breaking out of inner loop; 103 won't be reached.

Outer: 3; Inner: 101

Outer: 3; Inner: 102

Breaking out of inner loop; 103 won't be reached.

Use break with caution; sometimes it's the simplest way to do what you want, but more often it makes code hard to understand. If the following loop has no breaks in it, you can tell at a glance that it will execute 10 times:

for Times = 1, 10 do

A bunch

of code

goes here.

end

But if the line if Times == 5 then break end is in the middle, the loop will execute 4½ times, which is a bit harder to hold in your head while you're looking for a bug.

A break must be the last statement in a block. A block is a group of statements between the following:

· do and end

· repeat and until

· then and elseif, else, or end

· elseif and end

· else and end

In other words, a block is a do block (more about these in a moment), a loop, or a branch of an if statement. There are other blocks too, but these are the ones relevant to break. The following example demonstrates the error caused by trying to use break as something other than the last statement in a block:

> while true do

>> break

>> print("Never reached")

stdin:3: 'end' expected (to close 'while' at line 1) near 'print'

This limitation is not a hardship, because even if you could put statements after a break, they would never get executed. During debugging, however, it can be convenient to break out of the middle of a block, and you can do this by wrapping the break in its own block. Lua's final compound statement, the do block, is useful for this, as you can see in the following example:

> for N = 1, 10 do

>> print("Before")

>> do break end

>> print("After")

>> end

Before

>

The do block has the following form:

do

zero or more statements

end

It can also be used to force code typed directly into the interpreter to be executed as one unit, as in the second of the following examples, which, unlike the first, has all of its output in the same place, instead of it being interleaved with the code:

> print("\nHere are some numbers:")

Here are some numbers:

> for N = 1, 5 do

>> print(N)

>> end

1

2

3

4

5

> print("There were some numbers.")

There were some numbers.

> do

>> print("\nHere are some numbers:")

>> for N = 1, 5 do

>> print(N)

>> end

>> print("There were some numbers.")

>> end

Here are some numbers:

1

2

3

4

5

There were some numbers.

Summary

This chapter introduced you to the most fundamental elements of the Lua programming language. Most of the examples were given as typed into lua, the Lua interpreter. In this chapter, you learned the following:

· Numbers, strings, Booleans, and nil are different types of values.

· To print a value, use print and parentheses.

· You can use operators to do math, compare values, concatenate strings, and do various other things with values.

· Operators are applied in order of their precedence, but you can use parentheses to control this.

· You use a single equal sign to assign a value to a variable.

· Variable names (identifiers) must include only letters, digits, and underscores, and begin with a letter or an underscore. You cannot use keywords such as and, true, and if as variable names.

· Comments start with two dashes.

· Literal values and variables are expressions. You can build more complex expressions from less complex ones with operators and parentheses.

· Statements are the smallest complete unit of Lua code.

· To determine whether to do something, or how many times to do something, you use the control structures if, for, while, and repeat.

Often in this chapter, you have given names to values using assignment. it's possible to give names to pieces of code too. For example, you can write a big if structure and give it a name, and then when you want to use it, you don't have to type the whole thing in again, you just need to type the name. Pieces of code that are nameable like this are called functions, and They're the subject of the next chapter. Before leaving this chapter, though, take some time to do the exercises and test your understanding of what you've learned so far. You'll find answers in the appendix.

Exercises

1. Why does the following code give an error message rather than printing “Hello”?

> Print("Hello")

stdin:1: attempt to call global 'Print' (a nil value)

stack traceback:

stdin:1: in main chunk

[C]: ?

2. Assuming X is true and Y is nil, what is the value of the following expression?

(X and "ABC") .. (Y and "DEF" or 123)

3. The expression from the previous exercise does not have a value if X is false. Why is that?

4. Consider the following if statement:

if N < 10 then

print("x")

elseif N > 0 then

print("x")

end

If N is 5, how many x's will be printed?

5. Write a for loop that prints out the even numbers between 2 and 10, inclusive, in reverse order.