Variables and data types
This guide is the first in a series of Ruby courses. In this first chapter, we learn how to store information in variables.
No prior programming knowledge is required. We start from scratch.
Prerequisites
Before starting, Ruby and a code editor must be installed on your machine. If this is not yet done, follow the guide "How to set up your development environment" in the Miscellaneous section of the tutorials.
Testing code with IRB
Throughout this chapter, we will write small bits of code to understand each concept. The quickest way to test Ruby is to use IRB (Interactive Ruby). It is a console that executes Ruby line by line and immediately displays the result.
To launch IRB, open a terminal (in VSCode: menu Terminal > New Terminal) and type:
irb
You get a prompt irb(main):001:0> where you can type Ruby:
irb(main):001:0> 1 + 1
=> 2
irb(main):002:0> 'Pikachu'.length
=> 7
- Each line is executed immediately. The result is displayed after
=>. - To quit IRB, type
exit. - IRB is perfect for testing a quick operation, checking a behavior, or experimenting. We will use it a lot in the first chapters.
Principle
A program manipulates data: a name, a number, a list. To use this data, it needs to be stored somewhere. That is the role of a variable: a name that points to a value.
You can think of a variable as a label stuck on a box. The label (the name) lets you find what the box contains (the value). At any time, you can change the contents of the box without changing the label.
Creating a variable
In Ruby, creating a variable is as simple as writing a name, the = sign, then the value you want to store:
name = 'Pikachu'
level = 25
nameis the variable name. We chose this name; it could be anything else.=is the assignment operator. It says "the variable on the left now contains the value on the right".'Pikachu'is the value we store: here, text (called a character string or String).levelstores an integer (Integer).
We can then use these variables anywhere we would have used the value directly:
name = 'Pikachu'
level = 25
puts name # Displays: Pikachu
puts level # Displays: 25
putsis a command that displays a value on screen. It is one of the first tools we use to verify that our code does what we expect.
Changing the value of a variable
You can replace the contents of a variable at any time. The old value is simply forgotten:
name = 'Pikachu'
puts name # Displays: Pikachu
name = 'Eevee'
puts name # Displays: Eevee
- The variable
namefirst points to'Pikachu', then to'Eevee'. The name does not change, only the contents change.
Data types
Not all values are alike. A name is text, a level is a number, a legendary status is true or false. Ruby distinguishes these different data types. Let's look at the main ones.
Integers (Integer)
An Integer is a number without a decimal point. It is used for levels, Pokedex numbers, hit points:
pokedex_number = 25
level = 50
max_team_size = 6
For large numbers, Ruby allows underscores _ to make reading easier. The program ignores them completely:
# These two lines are identical for Ruby
experience = 1000000
experience = 1_000_000
Decimal numbers (Float)
A Float is a number with a decimal point:
damage_multiplier = 1.5
capture_rate = 0.75
- Floats are used when decimal precision is needed, such as damage multipliers.
Text (String)
A String is a sequence of characters surrounded by quotes. Ruby accepts single quotes '...' or double quotes "...":
pokemon_name = 'Pikachu'
description = "An adorable Electric-type Pokémon"
The difference between the two is important. Double quotes allow you to insert variables into text using the #{} syntax. This is called interpolation:
name = 'Pikachu'
level = 25
# With double quotes: interpolation works
puts "#{name} is level #{level}" # Displays: Pikachu is level 25
# With single quotes: interpolation does NOT work
puts '#{name} is level #{level}' # Displays: #{name} is level #{level}
- Interpolation is very handy for building sentences from variables. We will use it constantly.
- Simple rule: if the text contains variables, use double quotes. Otherwise, single quotes are fine.
Symbols (Symbol)
A Symbol looks like a String, but it starts with : and has no quotes:
pokemon_type = :electric
status = :healthy
What is the difference from a String? A Symbol is a fixed identifier. You never modify it; you compare it. It is like a label carved in stone, while a String is text that can be rewritten.
In practice:
- Use a Symbol when the value is an identifier: a Pokemon type (
:fire,:water), a status (:poisoned), a nature (:adamant). - Use a String when the value is text displayed to the user: a name, a description, a message.
# Symbol -- an identifier, always the same
pokemon_type = :electric
# String -- text intended for display
pokemon_name = 'Pikachu'
Booleans (true / false)
A boolean represents a value that is either true (true) or false (false). It is used for questions whose answer is yes or no:
is_legendary = false
is_alive = true
has_mega_evolution = true
- There is no
Booleanclass in Ruby.trueis of typeTrueClassandfalseis of typeFalseClass. This is a quirk of the language; no need to remember it for now.
The absence of value (nil)
Sometimes a variable simply has no value. In Ruby, nil is used to say "nothing", "empty", "not defined":
held_item = nil
secondary_type = nil
nilis not zero, nor an empty string. It is the total absence of value.- A single-type Pokemon has no secondary type.
nilexpresses exactly this idea.
Knowing the type of a value
Ruby allows you to ask any value what its type is. Two tools are useful for this:
puts 'Pikachu'.class # => String
puts 25.class # => Integer
puts 1.5.class # => Float
puts :electric.class # => Symbol
puts true.class # => TrueClass
puts nil.class # => NilClass
.classasks a value "what type are you?".
You can also ask the question differently: "are you of this type?":
puts 25.is_a?(Integer) # => true
puts 25.is_a?(Float) # => false
puts 'Pikachu'.is_a?(String) # => true
.is_a?answers withtrueorfalse. The?at the end of the name is a Ruby convention: methods that ask a question end with?.
Displaying and debugging
We saw puts for displaying. There is a second very useful tool: p.
name = 'Pikachu'
types = [:electric]
puts name # => Pikachu (clean display, for the user)
p name # => "Pikachu" (technical display, for the developer)
puts types # => electric (displays each element on a line)
p types # => [:electric] (shows the complete structure)
puts nil # => (displays an empty line)
p nil # => nil (displays the word nil)
putsdisplays the value in a readable way. It is what we use for messages intended for the user.pdisplays the value in a technical way, with quotes, brackets, etc. It is what we use when we want to understand exactly what a variable contains. It is a debug tool.
Compound assignment operators
We often need to modify a variable based on its current value. For example, increasing experience by 100 points. We could write:
experience = 0
experience = experience + 100
puts experience # => 100
Ruby offers a shortcut with +=:
experience = 0
experience += 100 # Equivalent to: experience = experience + 100
puts experience # => 100
Here are the main shortcuts:
experience = 100
experience += 50 # addition => 150
experience -= 20 # subtraction => 130
experience *= 2 # multiplication => 260
experience /= 4 # division => 65
experience %= 10 # modulo (remainder of division) => 5
+=is by far the most common. The others are useful but less frequent.- The modulo (
%) returns the remainder of a division.10 % 3gives1because 10 divided by 3 is 3 remainder 1.
Naming your variables
In Ruby, variable names follow a convention called snake_case: all lowercase, words separated by underscores:
# Good names
pokemon_name = 'Pikachu'
max_health_points = 142
is_legendary = false
# Bad names -- avoid these
pokemonName = 'Pikachu' # this is camelCase, not used in Ruby
n = 'Pikachu' # too short, impossible to understand
x = 142 # same problem
- A good variable name describes what it contains. Anyone reading the code should understand without effort what each variable represents.
- Never abbreviate:
pokemon_nameand neverpkmn_nameorpn.
Constants
Some values never change during program execution. The maximum number of Pokemon in a team is always 6. They are defined as constants, in uppercase:
MAX_TEAM_SIZE = 6
POKEDEX_VERSION = '0.1.0'
TYPE_FIRE = :fire
- Constants use
SCREAMING_SNAKE_CASE: all uppercase, separated by underscores. - Ruby displays a warning if you modify a constant, but does not prevent it. It is a convention, not a technical restriction.
Conclusion
- A variable is a name that points to a value. It is created with
=. - Ruby has 6 fundamental types: Integer (whole number), Float (decimal number), String (text), Symbol (identifier), Boolean (
true/false), and nil (absence of value). - Symbols serve as identifiers (
:fire,:water). Strings serve for displayed text. - Interpolation (
"#{variable}") inserts a variable into text. It only works with double quotes. putsdisplays for the user,pdisplays for debugging.- Variable names use
snake_case. Constants useSCREAMING_SNAKE_CASE. .classgives the type of a value..is_a?checks whether a value is of a certain type.