Odin Tutorial, Chapter 1: Humble beginnings

Beginner friendly tutorial series for the Odin programming language

Chapter 1: Humble beginnings

Today I was trying to encourage my friend to learn the odin programming language. But then to my dismay I found that there were no beginner friendly resources to learn from. So I’m rectifying this issue. Welcome to the first beginner friendly tutorial series for the Odin programming language.

First of all, you must have Odin installed on your computer. Since I am running arch linux, I can simply type yay -S odin-git in my terminal to install it. Linux users, you must check your repos or build it from source. Windows users, consult the website odin-lang.org. More handholding than that, I cannot give, because the process will vary so much from system to system.

Assuming now that you installed odin, either by yourself or with the help of a friend, we will create our first program. Open a command prompt, cmd on windows, any shell on linux. Then type the command mkdir my_odin_program to create a fresh directory for our work. Switch to the directory with the command cd my_odin_program.

Now that we have our terminal environment ready, let’s create a file called hello_world.odin inside our new directory and put the following contents inside.

package main

import "core:fmt"

main :: proc() {
    fmt.println("Hello world!")
}

Tabs versus Spaces does not matter, although I will judge you harshly if you use tabs. (Pressing the tab button is fine, but you editor should be inserting 4 spaces when you do so if it’s being a fine lad.)

In the terminal, run the program by typing odin run . then pressing enter. You should see the output text Hello world! if everything is working as it should. If this is not what you see, find out what the problem is. I will be henceforth assuming this worked and you saw the correct output.

What does it all mean?

It is time for my explination of the above program code and how it works. Although you will be well served by your curiosity when learning programming, it is wise to ‘move on’ so to speak when you know enough to accomplish the task at hand. In this vein I will offer a sufficient but not exhaustive explination. If you wish to learn more, have a look at odin-lang.org/docs/overview/.

package main

All you need to know about this statement is that it tells Odin that this file is a program to be executed, not a library. Since most of your programs will be single file in the near future, don’t worry about this too much other than that it should be at the top of your file.

import "core:fmt"

This tells Odin that we would like to import the package called fmt the core library collection that is included with the Odin compiler. I believe the official pronounciation of fmt is “fumt”, irrelevant but you might have been wondering. I said fmt is a package, you might be wondering, is it being fulfilled by amazon? The answer is no, because in this context a package is simply a bundle of code we would like to use. It is sometimes useful to reuse code, packages allow us to do that.

main :: proc() {
    fmt.println("Hello world!")
}

This is where it gets a little bit more complicated. Let’s start with the first bit, main ::. This tells Odin that there is a “thing” called main. In technical speak we would say that that we are declaring an identifier. An identifier is what it sounds like, it’s a “thing” that identifies something. To demostrate, replace the word main with the word dog, save the file and try to run the program again. You should receive this error.

/home/sam/my_odin_program/hello_world.odin(1:2) Undefined entry point procedure 'main'

The reason for this error, is that the Odin compiler is looking for a procedure called main. Since we renamed the identifier in our program to dog it cannot compile the program. An odin program always starts in the procedure called main, remember this.

So what is a procedure? In the context of programming it simply means a piece of code that does some things and can be invoked. If you’ve used other programming languages they might refer to this concept as a “function” or a “method”. The reason we don’t say function is because that can be confused with the more mathematical concept of a function. And we don’t use the term “method” because God punishes those who do.

Now, what does the stuff after main :: do? Well, it defines what the identifier main is refering to. proc() means, “there is a procedure” and what’s between the curly braces ({ ... }) are the contents of the procedure. Since I said a procedure is a thing that does stuff. What does our procedure called main do? Right now it does only one thing, it invokes a procedure from the package we imported earlier.

I’m realising that invoke might be a new word for some of you, so lets learn some etymology. Invoke comes from the latin word invocāre, which means “to call upon”, similar to how in Pirates of the Caribean, Elizabeth invokes “the right of parlay”. Programming is just like the movie, when a procedure is invoked, actions are carried out. Invoking main runs our program, invoking the procedure println(short for print line) from the package fmt, prints things in the terminal. (Final tangent, the reason it’s called printing comes from the days when computers were connected to electric typewriters not displays. So the output of a program was litterally printed on paper.)

Say we wanted to expand our program to also print out Hello sailor!. Then we can simply add another procedure call. (Procedure call = Procedure invokation) Now our program is as follows.

package main

import "core:fmt"

main :: proc() {
    fmt.println("Hello world!")
    fmt.println("Hello sailor!")
}

Exercices

Until the next tutorial, try change the program to print out a list of all your friends! Or if you don’t have any friends, you could use the names of Roman Emperors instead.

Smartypants

When I learned programming a decade ago. The book I was learning from had a “smartypants” section at the end of each chapter as an addition to the regular exercises. I think it was a good concept so I’m going to repeat it.

Can you create a second procedure that prints stuff that you call from the procedure called main?

And once you have done that, what happens if this second procedure invokes itself?

And if you are still curious, try perusing the webpage odin-lang.org/docs/overview/. See how much you understand.