Values and bindings
Chapter 1 left us with two names, price and items, and an error when we
tried to multiply them. We’ll come back to that. First, give a few values
names of their own:
let name = "Ada"
let messages = 3
print("\(name) has \(messages) messages.")
Ada has 3 messages.
let binds a name to a value. Here name holds text and messages holds a
whole number. Hirundo works out their types from what you gave them; you
don’t need to write String or Int beside each name. The interpolation
from hello.hir works with numbers too.
A let binding keeps the same value. When the value needs to change, use
var instead:
var messages = 3
messages = messages + 1
print("Now there are \(messages) messages.")
Now there are 4 messages.
The assignment changes messages from 3 to 4. Its type stays Int;
reassignment doesn’t let the name switch to a String halfway through the
program. An annotation works on var too, though this one needs none.
A type worth writing down
An annotation goes after the name. Most of the time inference is enough, but an annotation can tell Hirundo which type you want when a literal would otherwise leave it to choose:
let ratio: Double = 2
print(ratio * 1.25)
print(2.5 * 3)
2.5
7.5
let ratio: Double = 2 asks for a Double. The 2 can supply one even
without a decimal point. The next line multiplies that Double by 1.25.
The last line works for the same reason: in 2.5 * 3, the integer literal
3 can become a Double while the expression is being typed.
On its own, a whole-number literal normally becomes an Int; a decimal
literal normally becomes a Double. Once either value is bound to a name,
that name has a type. It doesn’t keep the literal’s flexibility.
Back to the error
Here’s the program from chapter 1:
let price = 2.5
let items = 2
print(price * items)
error: 3:13 cannot multiply a Double by an Int
items is already an Int. Hirundo won’t silently turn it into a
Double to match price, though the literal 2 could have taken on that
type directly in price * 2. To make the choice yourself, write
Double(items). Try it with three items:
let price = 2.5
let items = 3
print(price * Double(items))
7.5
This time the multiplication has two Double operands. The conversion is
visible where it matters; items itself hasn’t changed type.
Questions with true-or-false answers
A comparison produces a Bool: true or false. The > operator asks
whether the left number is greater; == asks whether two numbers are equal.
The two equals signs matter: a single = is the assignment you used with
messages. Try both comparisons:
let temperature = 22.5
let threshold = 23
print("Past 22? \(temperature > 22)")
print("At 22.5? \(temperature == 22.5)")
print("Past threshold? \(temperature > Double(threshold))")
Past 22? true
At 22.5? true
Past threshold? false
The 22 in the first comparison can take its type from temperature.
The bound threshold cannot, so the last comparison uses
Double(threshold). The rule is the same one you met with multiplication;
a comparison doesn’t get a secret conversion of its own. Other numeric
comparisons use !=, <, <=, and >=, and also answer with a Bool.
You have met four useful types: Int for whole numbers, Double for
decimals, String for text, and Bool for true or false. These four
may carry you further than you expect.
Next, we’ll use a Bool to let a program choose what to do.