Skip to content

Values and variables

Lesson 3.1

Every piece of data in Lua is a value, and a variable is a name you give to a value so you can use it later.

Values and their types

Each value has a type. Lua has eight:

Type Examples Used for
nil nil “nothing here”
boolean true, false yes/no answers
number 64, 0.5, -3 counts, health, coordinates
string "Diamond", 'Steve' text
table { 1, 2, 3 } lists, records, objects
function print code you can call
userdata (made by the host) game objects such as players
thread (made by coroutine.create) coroutines

The type function tells you the type of any value, as a string:

print(type(64))        --> number
print(type("Torch"))   --> string
print(type(true))      --> boolean
print(type(nil))       --> nil
print(type({}))        --> table
print(type(print))     --> function

You will meet every type in this course. Userdata is the only one you never create yourself: in Celestial, things like players and entities are userdata that the game hands to you.

Variables

A variable stores a value under a name. Create one with local:

local health = 20
local name = "Steve"

print(name, health)  --> Steve	20

The = sign means “store the value on the right in the name on the left”. It is not a maths equation. You can store a new value any time:

local health = 20
health = health - 4   -- take 4 damage
print(health)         --> 16

A variable has no fixed type. The same variable can hold a number now and a string later, although that usually makes code confusing.

Names

Names may contain letters, digits and underscores, and must not start with a digit. Case matters: score, Score and SCORE are three different variables.

local max_stack = 64       -- good
local playerName = "Alex"  -- also fine
local _unused = 0          -- a leading underscore often means "not used"

You can’t use the 22 keywords as names: and, break, do, else, elseif, end, false, for, function, goto, if, in, local, nil, not, or, repeat, return, then, true, until, while.

Most Lua code, including the Celestial API, uses snake_case: lowercase words joined by underscores.

nil: the missing value

A variable that was never given a value holds nil:

local pickaxe
print(pickaxe)  --> nil

nil means “no value”. Setting a variable to nil throws its value away.

Local and global variables

Without local, you create a global variable, which every part of the program can see:

coins = 10      -- global
local gems = 2  -- local

print(coins, gems)  --> 10	2

This looks harmless, but globals cause bugs: two files that both use a global called count silently overwrite each other. Reading a global you never set also gives nil instead of an error, so a typo goes unnoticed:

local score = 5
print(scroe)  --> nil

Always write local

Use local for every variable. It is faster, and it keeps each part of your code separate. In Celestial, each mod runs in its own sandbox, but inside your mod the same rule applies.

A local variable exists from the line where it is declared to the end of its block. Blocks are the bodies of if, loops and functions, or a do ... end pair:

local x = 1
do
  local x = 2      -- a new x, only inside this block
  print(x)         --> 2
end
print(x)           --> 1

The inner x shadows the outer one. Both exist; inside the block the name means the inner one.

Several variables at once

You can assign several values in one statement. The values are matched up left to right:

local x, y, z = 10, 64, -5
print(x, y, z)  --> 10	64	-5

Extra names get nil, extra values are dropped:

local a, b = 1
print(a, b)     --> 1	nil

This makes swapping two values easy:

local first, second = "Stone", "Dirt"
first, second = second, first
print(first, second)  --> Dirt	Stone

Constants

Lua 5.4 lets you mark a local as <const>. Assigning to it again is an error that Lua reports before running anything:

local MAX_HEALTH <const> = 20
print(MAX_HEALTH)  --> 20
-- MAX_HEALTH = 30  would be an error: attempt to assign to const variable

Many programmers simply write constants in UPPER_CASE and don’t change them.

Try it

Create local variables for a player called "Alex" with 20 health and 3 arrows. The player shoots one arrow and takes 6 damage. Update the variables and print the name, health and arrows on one line. Then print the type of each variable.

Show a solution
local name = "Alex"
local health = 20
local arrows = 3

arrows = arrows - 1
health = health - 6

print(name, health, arrows)                    --> Alex	14	2
print(type(name), type(health), type(arrows))  --> string	number	number

Recap: values have types, local name = value stores them, and a missing value is nil.