Welcome!
The document you are reading is a "Livebook", a kind of notebook that can be edited and used by multiple people and contain dynamic content like code, charts, buttons, videos and much more.
The facilitator should have demonstrated how to get it running on your computer and the basics of using the tool.
It is an ancient tradition amongst programmers that the first program one writes is called "Hello World". That's because all the program does is to print those two words on the screen.
We will do the same as our first exercise.
Click inside the black box below and type Hello world!
.
Then press the keys Ctrl + Enter
(on Windows) or Command + Enter
(on Mac) to run the program.
Hello World!
If you did that correctly, you should see a red notice and an error.
That's because programming languages treat text differently than human languages. Anything we type into the black box is assumed to be code instructions. And those two words don't match any existing instructions, so it leads to an error.
Let's instead try to tell the computer that these are in fact just two ordinary words and not a piece of code. We can do that, by wrapping the two words in double quotes ("
).
Try it below and run the code:
This time there should be no error, instead you should see the same words repeated back at you, now in green text.
So we know how to type text that the computer can work with. Let's learn how to reuse our text.
We can use a concept called "variables", which exists in all programming languages. (You might remember that word from math class, where they serve a similar purpose.)
You can think of variables as containers or boxes, that can store other things. Things like text, numbers, images, or almost anything else. By putting a thing in labeled box, we make it easier to find and reuse later.
Say we want to store the name of our user in a variable, so we can greet them when they run our program.
To create a variable, we first have to come up with a good label for it. In this case, name
seems pretty approriate for storing someones name!
(Note how name
is not in quotes because it is a variable and not a piece of text!)
After the label, we add a =
(equals symbol), followed by the thing we want to store. In this case it is the name of our user, "Grace"
.
So by using an equal symbol, we are telling the computer that these two things are equivalent, ie. they refer to the same thing. So the next time it sees name
, it will look it up in its memory and gives us the content inside, which is "Grace"
.
Here's how that looks:
name = "Grace"
Once we set a value for a variable, we can get the stored contents back by calling the variable itself. Click inside the code block below and press Ctrl+Enter
to run it.
name
Now we know how to store and access the name. But what if we want to combine some text with a variable?
For example, outputting "Hello Grace" using our name
variable. How can we achieve this?
We saw in the first exercise that we need to use double quotes (""
) to tell the computer that we are giving it ordinary text and not code instructions. What happens if you use the variable name
within double quotes? Try it out below.
"Hello name"
This will just treat the word name
as regular text, and not as code, therefore outputting "Hello name" instead of our desired "Hello Grace".
Elixir has a way to tell the computer that a variable needs to be replaced instead of treated as part of the text. The variable name can be wrapped inside curly braces preceded by a hashtag symbol: #{variable}
.
Try to run the example below:
"Hello #{name}"
This way, the output contains the original text and the variable placeholder has been replaced by the contents. In this case it is "Grace", but it could also have been "Peter" or "Ben" or whatever we decided to put inside the variable when we created it.
Write a small text where you can say your name and age, using variables for the name and the age.
We would like to make programs that can do more than just printing text. To do that we need a way to structure and organize our code.
Functions in Elixir are a basic concept that helps us group a set of instructions together.
They work similarly to functions in math: they take some input, do something with the input, and return an ouput.
We will create and use one function for each action that we want our program to do.
Functions are defined with the def
keyword (short for define), it is shown in purple in the code box.
Functions have a unique name that allows us to identify and reuse them, shown in blue.
The name of the function is generally written in what is called snake_case
, which means words connected by underscores. (So "My beautiful function" would usually be written as my_beautiful_function
)
Right after the name we chose, we write the word do
, to indiciate that anything that follows is what the function should do.
Then we can define any instructions on the next lines.
Once we are done, we use the word end
to indicate that we have reached the end of the function and no more work should be done.
def my_function_name do
"Hello Grace"
end
Elixir has also another type of function, but we will not talk about it at this point. As you might have noticed if you tried to run the above code, this will error. That's because a function needs to have a home. It needs to be placed inside what we call a module.
We can use modules to organize our functions. A module can contain one or more functions.
A module is opened with the defmodule
keyword, followed by a name of our choosing, and then a do...end
block containing our actual function.
The module name is generally written in what it is called "CamelCase", meaning no spaces and the first letter of each word capitalized. (So "My beautiful module" would usually be written as MyBeatifulModule
)
defmodule MyModuleName do
def my_function_name do
end
end
Once we have a function within a module, we could place our previous istruction in the function:
defmodule GraceGreeter do
def greet_grace do
"Hello Grace"
end
end
How can we print the text after this step? We do that by calling the function, using its name. And because the function is placed within the module, we need to tell the computer where the function is located and what it is called. So we call the module name, and chain the function name to it with a dot:
GraceGreeter.greet_grace()
We are however not yet done. How does it work if we want to be able to greet different people than Grace? We can combine the use of a variable that we saw above with our function. How will that look like?
defmodule PersonalGreeter do
def greet do
"Hello #{name}"
end
end
This gives us an error. Lets try to understand what is going on. The compiler complains that the variable name is undefined. What does this mean? In our previous example, we had given our name
variable a value. Now, in our new implementation with a module and a function, we are not giving the name variable a value, so the computer does not know what to print for name. How can we give a value to our variable used inside a function? Naturally, we could extend our code and give the variable a value:
defmodule NewGreeter do
def greet do
name = "Leia"
"Hello #{name}"
end
end
But what is the issue with this? You can probably spot the issue if you run this code as we learnt above:
NewGreeter.greet()
What is the issue? We are using a variable, but this variable will always give us the same output. So, how can we use a module and a function to greet different people? We need to somehow be able to give the function the value we want it to use when we run the code. We do this using something called parameters
. Parameters are used in two places:
- in the function
definition
:
defmodule SmarterGreeter do
def greet(name) do
"Hello #{name}"
end
end
where we define the variable name we are going to use
- in the function
call
:
SmarterGreeter.greet("Luke")
where we tell the computer which value to use for the variable name.
Write a module with functions that greet you in english and danish, giving you the following output and taking as inputs the name and the language of the greeting.
"Hej Grace"
"Hello Grace"
TODO: Function that does something more interesting
Calling built-in functions
"Hello #{name}, your name is #{String.length(name)} characters long"
defmodule LoudGreeter do
def shout(name) do
"HELLO #{String.upcase(name)}, CAN YOU HEAR ME?!"
end
end
LoudGreeter.shout(name)