Variables and types
What is a variable?
Imagine a box with a label on it. You can put something inside the box, and later you can look at the label to find what's inside. That's a variable.
A variable has three parts:
- A name (the label on the box)
- A value (what's inside the box)
- A type (what kind of thing can go in the box)
Creating variables
In Nyx, there are two ways to create a variable:
let — A value that doesn't change
fn main() { let name: String = "Alice" let age: int = 25 let pi: float = 3.14159 let active: bool = true print(name) print(age) }
let creates an immutable variable — once you assign a value, you cannot change it. This is the default and the safest option. Most of your variables should use let.
var — A value that can change
fn main() { var score: int = 0 print(score) // 0 score = 10 print(score) // 10 score = score + 5 print(score) // 15 }
var creates a mutable variable — you can change its value as many times as you want.
Why have both?
If you use let and accidentally try to change a value, the compiler will tell you. This catches mistakes early. Use var only when you genuinely need the value to change.
fn main() { let name: String = "Alice" name = "Bob" // ERROR: cannot assign to immutable variable }
The four basic types
Nyx has four fundamental types of data:
int — Whole numbers
fn main() { let count: int = 42 let negative: int = -7 let zero: int = 0 let big: int = 1000000 print(count) // 42 print(negative) // -7 }
Integers are whole numbers — no decimal point. They can be positive, negative, or zero. Use them for counting, indexing, and anything that doesn't need fractions.
float — Decimal numbers
fn main() { let temperature: float = 36.6 let price: float = 9.99 let ratio: float = 0.5 print(temperature) // 36.6 }
Floats are numbers with a decimal point. Use them for measurements, prices, percentages, and scientific calculations.
String — Text
fn main() { let greeting: String = "Hello" let empty: String = "" let sentence: String = "Nyx is a compiled language." print(greeting) // Hello print(sentence) // Nyx is a compiled language. }
Strings are sequences of characters — text. They are always enclosed in double quotes "...". Note that String starts with a capital letter — this is a convention in Nyx for complex types.
bool — True or false
fn main() { let is_active: bool = true let is_deleted: bool = false print(is_active) // true print(is_deleted) // false }
Booleans have only two possible values: true or false. They are used for conditions and decisions (you'll learn more about this in Chapter 4).
Type inference
In many cases, Nyx can figure out the type automatically:
fn main() { let name = "Alice" // Nyx knows this is a String let age = 25 // Nyx knows this is an int let pi = 3.14 // Nyx knows this is a float let active = true // Nyx knows this is a bool print(name) print(age) }
When you write let name = "Alice", Nyx sees the double quotes and knows the value is a String. You don't need to write : String explicitly — but you can if you want to be clear about your intentions.
For this book, we will write the types explicitly in most examples so you can see exactly what type each variable is. In practice, experienced programmers often let the compiler infer the types.
Naming rules
Variable names in Nyx must follow these rules:
- Start with a letter or underscore
_ - Can contain letters, numbers, and underscores
- Cannot be a reserved word (like
fn,let,var,if,while) - Are case-sensitive (
nameandNameare different variables)
fn main() { let user_name: String = "Alice" // good let age2: int = 25 // good let _temp: int = 100 // good let camelCase: String = "also fine" // good // let 2fast: int = 0 // ERROR: starts with a number // let let: int = 0 // ERROR: reserved word // let my-name: String = "" // ERROR: hyphens not allowed }
Convention: Nyx uses snake_case for variables and functions (words separated by underscores, all lowercase). Structs and types use PascalCase (each word capitalized, no separators).
let user_name: String = "Alice" // snake_case for variables let max_retries: int = 3 // snake_case for variables struct UserProfile { // PascalCase for types name: String, age: int }
Converting between types
Sometimes you need to convert a value from one type to another:
fn main() { // int to String let age: int = 25 let age_text: String = int_to_string(age) print("Age: " + age_text) // Age: 25 // String to int let input: String = "42" let number: int = string_to_int(input) print(number + 8) // 50 }
You cannot mix types directly:
fn main() { let age: int = 25 print("I am " + age) // ERROR: cannot add String and int }
Instead, convert the int to a String first:
fn main() { let age: int = 25 print("I am " + int_to_string(age)) // I am 25 }
Exercises
- Create variables for your name, age, and favorite number. Print all three.
- Create a mutable variable
counterstarting at 0. Increment it three times (add 1 each time) and print the result after each increment.
- Try creating a
letvariable and changing it. Read the error message the compiler gives you.
- What type would you use for each of these?
- The number of students in a class
- The temperature outside
- A person's full name
- Whether a light switch is on or off
Summary
letcreates an immutable variable (cannot be changed).varcreates a mutable variable (can be changed).- Four basic types:
int(whole numbers),float(decimals),String(text),bool(true/false). - Nyx can infer types, but you can write them explicitly.
- Use
int_to_string()andstring_to_int()to convert between types. - Variable names use
snake_case.
Next chapter: Operations and expressions →