Values and variables
Holding values in variables with local, the two kinds of number, text, booleans, nil, and asking a value what it is with type.
Variables, and the word local
A variable is a name for a value. In Lua you create one with local: local score = 10. The word local keeps the name inside the block where it was written, which is almost always what you want, so this course uses it from the start.
You change a value by assigning to the name again, and the old value is gone. A name is not a box with a fixed type; the same name can later hold text or a number.
Two kinds of number
Lua 5.3 keeps two kinds of number apart: integers, which are whole, and floats, which may have a fraction. 3 is an integer and 2.5 is a float, and print shows them differently so you can tell them apart.
Ordinary division always gives a float, so 10 / 4 is 2.5. When you want a whole answer, use // for floor division, and % for the remainder. 2 ^ 8 is a power, and it comes back as the float 256.0.
Text, booleans, and nil
Text sits in single or double quotes, and joining two pieces uses two dots: "Ada" .. " Lovelace". The # in front of a string gives its length in characters.
A boolean is true or false. There is one more value, nil, which means no value at all — it is the value a name has before anything is stored in it.
Names point at values
A Lua variable is a name in an environment, not a box with a fixed shape. local score = 10 binds that name to a number inside the block you are in. Assign again and the name points at a new value; the old one is simply no longer reachable from that name.
The type belongs to the value, not the name. The same local can hold a number and later a string, and Lua will not object. That freedom means the language cannot warn you at the assignment; it can only fail when an operation cannot use the value it was given.
When Lua converts, and when it refuses
Some operations convert for you. Arithmetic accepts a numeric string, and .. turns a number into text. Comparisons do not convert: "10" == 10 is false, and putting a string on one side of < raises an error rather than guessing. When a text value really has to become a number, say so with tonumber.
type answers with a string naming the kind of value, so type(2.5) is the text float. Use it when a value arrives from somewhere you do not control and the next line depends on what it is.
Integer and float are different types
math.type tells the two apart where type only says number: math.type(3) is "integer", and math.type(3.0) is "float". The distinction survives arithmetic. Adding two integers gives an integer; mixing in one float gives a float, which is why 7 / 2 is 2.5 and 7 // 2 is 3.
Floor division and remainder follow the sign of the divisor. -7 // 2 is -4, not -3, because floor division rounds toward negative infinity; -7 % 2 is 1. The quotient times the divisor plus the remainder gives the original number.
Shadowing, and the global trap
A local declared inside a block hides any outer name with the same spelling for as long as the block lasts. local x = 1 then do local x = 2 end leaves the outer x at 1. The inner name is a different variable that happens to share a spelling, and the outer one comes back at end.
A name assigned without local goes into the global table, which every part of the program shares. That is convenient in a five-line script and a source of bugs in anything larger: a typo creates a new global instead of an error, and one function can overwrite a name another relies on. Write local by default.
Every kind of value
local count = 3
local price = 2.5
local name = "Ada"
local ready = true
print(count)
print(price)
print(name)
print(tostring(ready))
print(type(count))
print(type(name))
print(type(ready))
print(count * 2)
print(name .. " has " .. count .. " items")Three habits prevent most early bugs. Write local every time you mean a variable — a name without it becomes global and can be changed from anywhere. Remember that / always gives a float, so use // when you want a whole answer. And never compare a value that arrived as text with == against a number: "3" == 3 is false even though arithmetic will accept the text.
Try these next
- Store a price and a quantity, then print the total and the type of the total.
- Divide 7 by 2 with
/and with//, and print both answers on one line. - Make a name with
localinside ado ... endblock, then try to print it after the block. Read the error.
Names for values
Run it and match each printed line to the value it came from. Then add a float of your own, print its type, and divide two integers to see the fraction appear.
A till, and the types behind it
Run it and follow the total. Then change the price and quantity, and print the type of `number` after the conversion.
Text and numbers join cleanly with two dots, but a boolean or nil does not. Wrap those in tostring first, which turns them into the words true, false or nil so they can sit inside a sentence.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
What does the word local do when you make a variable?
