2. Variables and Types¶
Learning Objectives
- be familiar with Lua variables and primitive types
- contrast between statically typed language vs. dynamically typed language
- be aware of the limitations of the dynamically typed languages
Primitive Types¶
Lua has a small but powerful set of primitive types which can be used to describe data:
nil
: Represents the absence of a value.boolean
: Can be true or false.number
: Lua uses double-precision floating-point numbers.string
: Immutable sequences of characters.table
: Associative arrays that can represent arrays, dictionaries, or objects.function
: First-class functions for procedural programming.thread
: Represents independent threads of execution (used for coroutines).userdata
: Used to store arbitrary C data.
We can use the type()
function to check the datatype of a value or a variable to return a string representation of the data type.
Since functions are first-class citizens in Lua, we can pass functions to other functions. This means we can also pass functions as callbacks to other functions, letting us form powerful higher-order functions.
Common mistake
While type()
works for Lua primitives, it returns "userdata"
for all Roblox data types. When dealing with Roblox data types, we must use the typeof()
function instead.
Variables¶
Variables are an abstraction to hold values which we can use to manipulate and pass around values. We can create variables simply by associating a variable name with its value. By default, all variables are global but we can make them local variables using the local
keyword:
Local variables follow standard block-scoping rules and are always faster to access and modify than global variables. For the rest of this course, we will exclusively use local variables.
Dynamic vs. Static Typing¶
Lua is a dynamically typed language which means that the same variable can hold values of different unrelated types. Note that, the type is associated with the values, and the type of the variable changes depending on the value it holds.
For example, we can do the following in Lua:
but we can't do the same in a statically typed language, such as Java or C:
int x; // declare x is variable of type int
x = 4; // ok, because x is still of type int
x = "5" // error, cannot assign a string to an int
This means that we don't have the same notion of compile time type and runtime type as in other languages like Java.
Runtime Type Checking¶
Notice that, due to Lua being dynamically typed, types can only be resolved at runtime and type checks too can only be done at runtime. While this provides flexibility, it can lead to potential issues in complex systems like games.
In game development, bugs caused by type mismatches can be especially problematic because games often involve long, interactive sessions with unpredictable player behavior. For example, consider the function mathPow(base, exp)
which expects numbers. If we accidentally pass in a invalid value like a table:
local base = 3
...
base = {} -- accidental
...
mathPow(base, 2) -- throws error only when the line is run
Lua won't detect this mistake when the code is written or loaded. Instead, the error will occur only when the code runs at that specific point. In a game, this might be a rare condition triggered only under specific gameplay circumstances. For example:
- Suppose this code is part of a damage calculation function for a boss enemy in a specific level.
- The player might not encounter this boss until hours into the game.
- When they do, the game could crash or throw a runtime error, disrupting the player’s experience.
Possible Solution: Input Validation¶
One way to partially deal with this problem would be do use input validation. We could always check the types explicitly before performing operations:
However, this is inelegant and we would also still not be solving the issue of being able to know at the type of writing code whether there are any type errors.
Ideal Solution: Type Annotation¶
Luau, the Lua variant used by Roblox adds static type checking through type annotations. We will cover Luau features in-depth in a later section but for now, here is an example of how Luau works: