Appearance
Strings, Numbers, and Nil
Written: 2026-10-14
Learning objectives
- You write strings with quotes, join them, and use escapes.
- You read numbers as doubles, including
0x,0b, and underscores. - You explain nil as non-existence.
- You predict when
==surprises you and compare the safe way.
Prerequisites
- Read First Script. You can run a Script and read output.
- Read Variables and Values. You create variables and print them.
- Read Operators and Logic. You join with
..and convert withtonumberandtostring. - Read Conditionals and Loops. You branch with
if. - Read Functions and Scope. You return values from functions.
- Read Tables, Part 1. You read table keys and positions.
Strings hold text
A string is a run of characters between quotes: letters, digits, spaces, and symbols. Double quotes and single quotes both work. Pick one style per script and stick with it. This course uses double quotes.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local greeting = "Hello!"
local quoted = 'She said hi'
print(greeting)
print(quoted)txt
Hello!
She said hiWalkthrough:
- Line 1 turns on strict mode.
- Line 2 stores
"Hello!"ingreeting. - Line 3 stores
'She said hi'inquoted. Single quotes work the same. - Lines 4 and 5 print both strings.
You already joined strings with .. in Operators and Logic. Joining never adds spaces. Put the spaces inside your quotes.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local firstName = "Maya"
local line = "Hi, " .. firstName .. "!"
print(line)
print(#line)txt
Hi, Maya!
9Walkthrough:
- Line 1 turns on strict mode.
- Line 2 stores
"Maya"infirstName. - Line 3 joins three pieces into
"Hi, Maya!". The space and comma come from inside"Hi, ". - Line 4 prints
Hi, Maya!. - Line 5 prints the character count,
9.
Escapes let quotes and special marks live inside strings. A backslash plus a character stands for one hard-to-type character: \" is a quote inside a double-quoted string, \\ is a single backslash, \n starts a new line, and \t inserts a tab.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local said = "She said \"hi\""
local lines = "one\ntwo"
print(said)
print(lines)txt
She said "hi"
one
twoWalkthrough:
- Line 1 turns on strict mode.
- Line 2 stores
She said "hi". Each\"becomes one real quote character without ending the string. - Line 3 stores two lines in one string.
\nbecomes a line break. - Line 4 prints
She said "hi"on one line. - Line 5 prints
oneandtwoon separate lines.
Numbers are doubles with handy spellings
Every Luau number is a double: a 64-bit decimal-friendly value. There are no separate integer and decimal types. 7 and 7.5 are both numbers.
Luau offers alternate spellings for whole values. 0x starts a hexadecimal (base-16) literal, like 0xFF for 255. 0b starts a binary (base-2) literal, like 0b1010 for 10. Underscores split long digits: 1_000_000 equals 1000000.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local red = 0xFF
local switches = 0b1010
local crowd = 1_000_000
print(red)
print(switches)
print(crowd)txt
255
10
1000000Walkthrough:
- Line 1 turns on strict mode.
- Line 2 stores hex
0xFF, which equals decimal255. - Line 3 stores binary
0b1010, which equals decimal10. - Line 4 stores
1_000_000. The underscores vanish. The value is1000000. - Lines 5 to 7 print
255,10,1000000.
Decimals bring tiny fuzz. 0.1 + 0.2 prints 0.30000000000000004, not a clean 0.3. This is normal for doubles in every language. For money or scores, round for display with tostring and formatting, or compare with a small tolerance instead of exact ==.
Nil means nothing is there
A variable holds nil when it was never assigned, when a function returns nothing, when a table key was never created, or when you deleted it. Reading any of those gives nil. It is not zero. It is not an empty string. It is the absence of a value.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local nickname = nil
local player = { name = "Maya" }
print(nickname)
print(player.title)txt
nil
nilWalkthrough:
- Line 1 turns on strict mode.
- Line 2 declares
nicknameholdingnil, meaning no nickname chosen. - Line 3 builds a table with only a
namekey. - Line 4 prints
nilfor the empty variable. - Line 5 prints
nilfor the missingtitlekey. Missing keys arenil, not errors.
Because only nil and false are falsy, you can guard with if value ~= nil then before using something that might not exist. And you delete a dictionary key by assigning nil, as you practiced in Tables, Part 1.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local player = { name = "Maya" }
if player.title ~= nil then
print(player.title)
else
print("no title yet")
endtxt
no title yetWalkthrough:
- Line 1 turns on strict mode.
- Line 2 builds a table with no
titlekey. - Line 3 compares
player.titleagainstnil. Since the key is missing, the test is false. - Line 6 runs the
elsebranch and printsno title yet.
Compare with ==, carefully
== asks "are these the same value?" For strings, numbers, and booleans, it compares content. For tables, it compares identity: two tables are equal only when they are the very same table, even if their contents match character for character.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local first = { "a", "b" }
local second = { "a", "b" }
local same = first
print(first == second)
print(first == same)txt
false
trueWalkthrough:
- Line 1 turns on strict mode.
- Line 2 builds one table and stores it in
first. - Line 3 builds a second, separate table with identical contents in
second. - Line 4 copies the reference, so
samepoints at the exact tablefirstpoints at. - Line 5 prints
false. Same shape, different tables. - Line 6 prints
true. Same table, so equal.
Two more == traps catch beginners. First, "5" == 5 is false because a string is never equal to a number. Convert with tonumber first. Second, 0.1 + 0.2 == 0.3 is false because of double fuzz. Compare the gap instead.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local typed = "5"
print(typed == 5)
print(tonumber(typed) == 5)
local total = 0.1 + 0.2
print(total == 0.3)
print(math.abs(total - 0.3) < 0.0001)txt
false
true
false
trueWalkthrough:
- Line 1 turns on strict mode.
- Line 2 stores the string
"5". - Line 3 prints
false. Text"5"and number5are different values. - Line 4 converts first, then compares, printing
true. - Line 5 adds the fuzzy decimals.
- Line 6 prints
false. The sum is0.30000000000000004, not exactly0.3. - Line 7 measures the gap with
math.absand asks whether it is tiny. This printstrueand is the safe way to compare decimals.
Common mistakes
Forgetting quotes around text.
Run this to see it fail: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local city = Paris
print(city)txt
nilParis with no quotes is read as a variable. That variable does not exist, so strict mode flags it and it arrives as nil. Fix it with quotes. Run the fix the same way.
luau
--!strict
local city = "Paris"
print(city)txt
ParisExpecting .. to add spaces.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local line = "Hi," .. "Maya"
print(line)txt
Hi,MayaThis prints Hi,Maya with no space. Fix it by putting the space inside a quote. Run the fix the same way.
luau
--!strict
local line = "Hi, " .. "Maya"
print(line)txt
Hi, MayaComparing a string to a number.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local typed = "5"
if typed == 5 then
print("five")
endtxt
This never prints because "5" and 5 differ. An empty output is the clue: the condition was false. Fix it by converting first. Run the fix the same way.
luau
--!strict
local typed = "5"
if tonumber(typed) == 5 then
print("five")
endtxt
fiveCalling two same-shaped tables equal.
Run this: put it in a Script in ServerScriptService and press Play.
luau
--!strict
local first = { "a", "b" }
local second = { "a", "b" }
if first == second then
print("match")
endtxt
This never prints because they are different tables. An empty output is the clue. Fix it by comparing contents entry by entry. Run the fix the same way.
luau
--!strict
local first = { "a", "b" }
local second = { "a", "b" }
if first[1] == second[1] and first[2] == second[2] then
print("match")
endtxt
matchExercises
Run every solution below in a Script in ServerScriptService and press Play. Try each exercise yourself before you open its solution.
- Store your first name. Print
"Hi, "joined with your name and"!", then print the length of the joined string.
Solution 1
luau
--!strict
local firstName = "Maya"
local line = "Hi, " .. firstName .. "!"
print(line)
print(#line)txt
Hi, Maya!
9- Store
0x10and0b10in two variables. Print both. Both should print decimal values.
Solution 2
luau
--!strict
local hex = 0x10
local bits = 0b10
print(hex)
print(bits)txt
16
2Hex 0x10 is sixteen. Binary 0b10 is two.
- Build
{ title = "Rookie" }. Printtitle. Delete it withnil. Print it again to show it is gone.
Solution 3
luau
--!strict
local badge = { title = "Rookie" }
print(badge.title)
badge.title = nil
print(badge.title)txt
Rookie
nil- A player typed
"9". Convert it, add1, and check that the result equals10. Print the sum and the boolean. Then show that0.1 + 0.2 == 0.3isfalsebut the tolerance check istrue.
Solution 4
luau
--!strict
local typed = "9"
local asNumber = tonumber(typed)
local total = asNumber + 1
print(total)
print(total == 10)
local fuzzy = 0.1 + 0.2
print(fuzzy == 0.3)
print(math.abs(fuzzy - 0.3) < 0.0001)txt
10
true
false
trueLine 3 converts text to a number before math. Line 8 shows exact decimal comparison failing. Line 9 shows the tolerance check passing.
Summary
You wrote strings with quotes, joined them with .., and embedded quotes and line breaks with escapes. You read numbers as doubles with 0x, 0b, and underscore spellings, and you treated decimals with tolerance. You read nil as non-existence, guarded missing keys, and compared safely: convert before ==, and never expect two separate tables to be equal.
Next: Debugging Basics.