Learning programming with Swift

Introduction

Programming is about telling a machine very very precisely what you want it to do.
The program code you are writing are instructions that tell the computer what to do.
The computer is in a sense very stupid because it will not do "what you meant",
but only exactly what you said.
If you have a large program with millions of lines of code,
one error in one line can make the whole program useless.

However, it's important to note,
that you basically cannot write a correct program on the first ry; except if it's very short.
As a programmer you first write some code,
test it out, discover lots of errors and then fix them.
This cycle is repeated until the code is correct.
Don't be afraid to write wrong code at the beginning!
Everyone does!

The other thing to know about programming is that is basically impossible to do
without re-using other people's code.
Lots of programers publish their code in the form of so-called libraries
that you can use.
The typical (useful) program makes use of dozens if not hundreds of libraries that other people wrote.
The idea is basically that someone solves a general problem once
and then other people can use the solution.

First steps

Consider this code:

let a = 2

We stated that the variable a should have the value 2.

Let's do something with a:

let a = 2
print(a)

This puts the value of a into the output of the program.
print is a function, which despite the name has little to do with printing.
The function print takes the argument that you give it
and evaluates it and puts it into the output of the program.

Now where does this function print come from?
Well, it is part of the so-called standard library of Swift.
The standard library was written by the creators of the Swift programming language.
It contains lots of functions that are useful to all kinds of programs.

Let's look at this code. What do you think is the output of the program?

let a = 2
let result = (+)(a, 4)
print(result)

We have here used a function which has a very weird name, namely (+).
Later, it will become clear why this name is so weird, but we'll ignore it for now.
As you might be able to guess, this function takes two arguments and adds them together.
It is also in the standard library of Swift.
This is a very nice function that someone wrote, so we don't have to write it.
Programmers use this function all the time.

Let's write our own function using (+).
Don't worry if you don't understand what's going on!
I will explain everything.

func addAndDouble(x: Int, y: Int) -> Int {
    let sum = (+)(x, y)
    let doubleSum = (+)(sum, sum)
    return doubleSum
}

let a = 2
let result = addAndDouble(x: a, y: 4)
print(result)

There are lots of things going on here.
Let's look at them one by one.

First we have the word func.
Like the word let, this is a keyword.
It is a word that has a special meaning in Swift
and you cannot use that word as the name of a variable.
This:

let func = 2

will give you an error and the program will not even run; let alone do what you want.

Now, while the keyword let is used to defining a new variable,
func is used to define a new function.
Following func is the function name.
In this case it's "addAndDouble".
In the parantheses are then the function arguments.
Let's ignore the business with the Ints for now:

func addAndDouble(x, y) {
    let sum = (+)(x, y)
    let doubleSum = (+)(sum, sum)
    return doubleSum
}

(this code won't work, but is illustrative)

Our function has two arguments (or "inputs") which we named x and y.
Arguments are kind of like variables.
We can give them any name we want (except names that are keywords).

Within the curly braces ({...}) we have the function body.
This is where we define what the function is supposed to do.
In this case we define a new variable called sum
which is equal to the sum of x and y.
Then we define another variable called doubleSum
which is equal to two times the value of sum.
This "double sum" is supposed to be the output of the function.
Thus, we use the keyword return to declare
that the value of doubleSum is the output of our function addAndDouble(x, y).
The keyword return is usually used at the end of the function body,
but there are also some special cases where it's useful to use it in other places.

Now let's add back the Ints. What are they about?

func addAndDouble(x: Int, y: Int) -> Int {
    let sum = (+)(x, y)
    let doubleSum = (+)(sum, sum)
    return doubleSum
}

Int specifies a type.
What is a type?
The type tells you what type of data a variable holds.
In our case, the variables hold numbers.
More specifically, whole numbers, which are integers.
And that's what the type Int refers to: integers.
x: Int simply tells the computer that x is supposed to be an integer.
And the -> Int means that the output of the function is also an integer.

Now, why do we have to specify the type of x and y?
Well, what we intend to do with x and y is add them together.
And you can only do that with numbers!
So, in order for our function to work, x and y have to be numbers.
That's why we're specifying the type Int.
Another function might take other types as inputs.

What other types of data are there?
The most basic ones are: Int, Double, String and Bool.
All the other data types are basically combinations of these.
Let's go through them.

Double

This type is for floating point numbers which refers to numbers like 3.2 or 0.003.
So, not whole numbers.
Our addAndDouble(x, y) function could also have accepted Doubles as arguments.
We can define a variable with a Double value like so:

let pi: Double = 3.14

But you might ask: why is this type called "Double"?
The name "Double" is short for "double precision floating point".
There are also single precision floating point, but we will ignore them for now.
Most languages treat floating point numbers by default as double precision,
so it is easier to work with Double.
I'm truly sorry about the confusing name, but that's just how this type is called in nearly every language.

As you would expect, you can use the (+) function with variables of this type:

let pi: Double = 3.14
let doublePi = (+)(pi, pi)

Now, you might wonder: if we have Double, why do we need Int?
After all, Int is a subset of Double.
The answer is that it is often useful to restrict an argument to Int.
But there are in fact programming languages that don't have Ints; only Doubles.

String

This is the type for text.
Why is this type called String and not, for example, Text or Letters?
It comes from "string of characters" and was defined in the 1960s.
It's not the greatest name, but basically all programming languages use it.

When we define a string variable, we use quotation marks:

let greeting: String = "Hello, world!"

Of course, a string can also contain a random mix of letters and numbers:

let nonsense: String = "2d;l8dfh;348fhea"

It's important to note that, for example, 9 and "9" mean two very different things.
These two variables do not contain the same value:

let a: Int = 9
let b: String = "9"

The first one contains a number that can be used to do math.
The second one is a string that happens to have a number in it.
The computer stores these very differently.
This can be a bit confusing at the beginning.

A string is certainly something that our function add(x, y) cannot accept as an argument.
And if you try to do

let f = addAndDouble(x: "Hello", y: 2)

you will get an error.
Which is good, because it doesn't make any sense.

Bool

This type might be a bit weird at first, but it is very useful.
Variables that have type Bool can only have 1 of 2 values: true or false.
The names true and false are keywords that cannot be used for variable names.
So, we might write:

let nice_weather: Bool = true

The name of the type, Bool, comes from the mathematician George Boole.
The usefulness of this type will become clear when we have introduced if-statements.


In the previous code, we have written variable definitions like

let a = 2

without type specification.
This is possible because when we write it like that,
it's obvious what kind of data the variable a contains: a 2 which is an integer.
But we can also write it explicitly if we want to:

let a: Int = 2

In fact, if you want to define a Double variable with the value 2, you have to specify it:

let a: Double = 2

Alternatively, you can also write 2.0:

let a = 2.0

Then a has type Double.


Let's recap what we have learned.
This:

func addAndDouble(x: Int, y: Int) -> Int {
    let sum = (+)(x, y)
    let doubleSum = (+)(sum, sum)
    return doubleSum
}

defines a function which takes two integers and gives one integer back,
which is two times the sum of the two inputs.

This code gives an error:

let greeting = "Hello"
let result = addAndDouble(x: greeting, y: 2)

because the variable greeting contains a string (i.e. text)
which is not a valid argument for the function add.

In our examples, we have made use of two functions from the standard library: print and (+).
There are of course many more.
Amongst them for example (-) for subtracting, (*) for multiplying and (/) for dividing numbers.

We have also already encountered the following keywords: let, func, return, true, false.
But there are a few more keywords to discover.


Lesson end
Next lesson: structs (use StructName.init() to initialize structs)

More from Thomas Kehrenberg
All posts