CodeRigor

LESSON

Name values with variables

Store whole numbers, decimals and text in local variables, calculate with them, and join text and values into lines of output.

The programs in the first lesson printed text that was fixed when you wrote them. Useful programs remember things and calculate with them. For that they need variables.

A variable is a name for a value

A value is a piece of data: a number, or some text. A variable is a name that refers to a value, so that you can use the value later by writing the name.

Lua
local price = 4
print(price)

This prints 4. Read the first line as "make a new variable named price and give it the value 4". Giving a variable a value is called assignment, and the = sign does it. It does not mean "equals" as in mathematics; it means "now refers to".

The word local creates the variable. Write it once, the first time you use a new name. Without it Lua would still accept the line, but it would make a global variable, one shared with every part of the program, which any other part could change by accident; local keeps the variable to the place where you made it, so Lua programmers start every new variable with local.

Notice that print(price) has no quotation marks. With quotation marks, print("price") prints the word price. Without them, Lua looks up what the name refers to and prints that.

Three kinds of value

You will use three kinds of value in this unit:

  • A whole number such as 4 or -12 is an integer.
  • A number with a decimal point such as 2.5 is called a float (short for "floating-point number", the way computers store decimals).
  • Text between quotation marks such as "notebook" is a string.
Lua
local quantity = 3
local price = 2.5
local item = "notebook"
print(quantity)
print(price)
print(item)

This prints 3, 2.5 and notebook on three lines.

Arithmetic

Lua calculates with the usual signs. A piece of code that works out to a value, such as 2 + 3, is called an expression.

Lua
print(7 + 2)
print(7 - 2)
print(7 * 2)
print(7 / 2)
print(7 // 2)
print(7 % 2)

This prints 9, 5, 14, 3.5, 3 and 1.

  • * multiplies.
  • / divides and always gives a float, even when the answer is whole: 6 / 2 is 3.0.
  • // divides and rounds down to a whole number: 7 divided by 2 is "3 and a bit", so 7 // 2 is 3.
  • % gives the remainder of that division: 7 is 3 twos with 1 left over.

Multiplication and division happen before addition and subtraction, as in school arithmetic. Round brackets change the order:

Lua
print(2 + 3 * 4)
print((2 + 3) * 4)

This prints 14 and then 20.

When one of the numbers is a float, the answer is a float: 2.5 * 2 prints as 5.0, not 5.

Assignment works out the right-hand side first

An assignment has two steps. Lua first works out the value of everything to the right of the =. Then it makes the name on the left refer to that value.

That is why this line makes sense, even though it would be nonsense in mathematics:

Lua
local apples = 5
local eaten = 2
local left = apples - eaten
apples = apples + 10
print(left)
print(apples)

This prints 3 and then 15. Line 4 has no local, because apples already exists: the line gives an existing variable a new value. Step through the diagram to see what each name refers to after each line.

What each name refers to, line by line
start / 5 ⇄ code
Each assignment works out the right-hand side first, using the values the names have at that moment. Changing apples on line 4 does not change left.
What each name refers to, line by line
Each assignment works out the right-hand side first, using the values the names have at that moment. Changing apples on line 4 does not change left.

A variable does not remember how its value was calculated. left was given the value 3; it is not a formula that follows apples around.

Choosing names

A name can contain letters, digits and the underscore _, and must not start with a digit. Capital letters count: total and Total are different names. Choose names that say what the value means: price and quantity are better than p and q. When a name needs two words, join them with an underscore, as in unit_price.

Joining text and values

Two dots, .., join two pieces of text into one string. Programmers call this concatenation.

Lua
local item = "notebook"
local quantity = 3
print("Item: " .. item)
print("Quantity: " .. quantity)

This prints:

Text
Item: notebook
Quantity: 3

The space after the colon is inside the quotation marks. .. adds nothing of its own, so any space you want must be in one of the strings. When one side of .. is a number, Lua turns the number into text for you. Put a space on each side of the dots, especially next to a number: 3..4 confuses Lua, 3 .. 4 does not.

How line 4 builds its line of output
start / 4 ⇄ code
Lua looks up the variable, turns the number into text, joins the two pieces, and only then calls print with the finished string.
How line 4 builds its line of output
Lua looks up the variable, turns the number into text, joins the two pieces, and only then calls print with the finished string.

You can join as many pieces as you like in one expression: "You bought " .. quantity .. " of them."

Money needs two decimal places

A float is printed with as many digits as it needs, so 2.5 * 3 prints as 7.5. A price should read 7.50. The function string.format builds a string from a pattern and a value:

Lua
local total = 2.5 * 3
print(total)
print(string.format("%.2f", total))
print("Total: " .. string.format("%.2f", total))

This prints 7.5, then 7.50, then Total: 7.50. The pattern "%.2f" means "a number with exactly two digits after the decimal point". Change the 2 to a 1 and run it again to see one digit.

Two errors you will meet

A misspelt variable name. The variable is total, but line 2 says totl:

Lua
local total = 12
print("Total: " .. totl)
Text
/usr/bin/lua: solution.lua:2: attempt to concatenate a nil value (global 'totl')
stack traceback:
	solution.lua:2: in main chunk
	[C]: in ?

Read the first line: line 2, and the name in brackets is totl. (The message calls it global because no local line ever created it.) Remember that nil means "nothing". Lua does not know any variable named totl, so the name refers to nothing, and nothing cannot be joined to a string. "Concatenate" is the name for what .. does. Whenever a message says nil value and names a variable, check the spelling of that name first.

Using + to join text. + is only for numbers:

Lua
local total = 12
print("Total: " + total)
Text
/usr/bin/lua: solution.lua:2: attempt to add a 'string' with a 'number'
stack traceback:
	[C]: in metamethod 'add'
	solution.lua:2: in main chunk
	[C]: in ?

Again the first line is the one to read: on line 2 you tried to add a string and a number. To join text, use ... The traceback is one line longer this time; the line of your program is still the one that starts with solution.lua:2.

What you can do now

You can create variables with local, store integers, floats and strings in them, calculate with + - * / // %, and build lines of output with .. and string.format. In the exercises you will trace what small programs print and then write a program that calculates and prints a receipt.

Next: read what the user types, so that a program can work with values it did not know in advance.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Starts at 'Data Types' (3:43) and runs into 'Math' (6:58 to 10:53): a brisk second look at Lua's kinds of value and its arithmetic. It moves quickly and was recorded in 2015 with an older version of Lua, so pause and try each line yourself.