I’m going to assume that you have Odin installed at this point. We are going to jump straight into writing our first little program, a program that just prints a message to the terminal and exits. It’s probably the simplest program we can write, so it’s a quick way to test that our setup is working properly. And we can start asking some basic questions.

Create a directory (folder). You can call it hellope, or some other name, if you wish. I personally avoid spaces in file and directory names and prefer to not use capital letters, for most part. In the folder create a file that ends with .odin. I will call it main.odin, but hellope.odin works just as well.

1
2
3
4
5
6
7
package main

import "core:fmt"

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

When you are done, save the file. We are going to try to run it. In your terminal, change into the directory where the file you created above is located and type the following. Don’t include the $, which I am using to indicate the command-line prompt. Your own prompt may look very different, like lorenzo@orthanc:~/fun or even C:/Home/Lorenzo/fun>. It doesn’t matter, just remember not to type the initial prompt. Make sure you include the period at the end.

$ odin run .

If everything went well, you should see:

$ odin run .
Hellope!

The terminal has 3 “communication channels” that it uses to communicate with the user (that is you in this case). Two of them are output channels (one for normal output and one for errors) and one is for input.

The procedure fmt.println prints to the normal output channel, which is usually referred to as standard output or stdout.

Finding and fixing errors

Things get more interesting if you didn’t get the output above, but itstead something else. For example, a particular error might get you a message similar to this.

lorenzo@orthanc:~/Projects/odin-playground/hellope$ odin run .
/home/lorenzo/Projects/odin-playground/hellope/main.odin(6:5) Error: Undeclared name: fm
        fm.println("Hellope!")
        ^^

This is an error message produced by the Odin compiler. It’s telling you something is wrong and gives you as much information as possible in order to find and fix the issue.

No matter how good you become, it’s likely you are going to make mistakes regularly. One of the main differences between a beginner and a more experienced programmer is how they respond to errors. The beginner might panic a bit and not know what to do. The experienced developer starts reading the error messages and uses them as an aid to quickly find and fix the errors.

If you look at the error message above you get quite a bit of information: something on line 6 caused the error and the error had something to do with fm not being declared. The program that caused this particular message looks as follows. Can you use the error message to find the bug?

Spend some time to get familiar with error messages.

1
2
3
4
5
6
7
package main

import "core:fmt"

main :: proc() {
    fm.println("Hellope!")
}

Try it out

In my mind, if you want to master programming, you should experiment a lot. Although this is a trivial program, there are a lot of things you can play around with. Here are some example questions you can ask and test by modifying the code:

  1. What happens if I change package main to package hellope? Will the program still work?
  2. Why do I need that first line anyways? What happens if I remove package main altogether?
  3. What error message, if any, do I get if I remove the import "core:fmt" line?
  4. I’ve heard that some other languages, might use or allow single quotes instead of double quotes. Does that work with Odin?
  5. Why even quote at all? Can’t I just remove the quotes?
  6. Do I have to type out Hellope!? I want to print something else.

Any time you wonder about something, try it out. The worst thing that can happen is that it doesn’t work, in which case you have learned something you cannot do.

Commenting a line

As you experiment with your programs, it might get annoying to remove lines only to have to retype them later. So one thing you can do is to comment a line out. To comment out a single line, put // at the beginning of the line (before any text). For instance, I wanted to find out what happens if I leave out the `package statement at the beginning of the line. Instead of removing the line, I commnented it out, so that the compiler will completely ignore that line, as if it weren’t there.

1
2
3
4
5
6
7
// package main

import "core:fmt"

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

If you wanted to comment out more lines of code, you could either put a // at the beginning of each line, or you could use a multi-line comment. This starts with a /* and ends with a */. Below I have commented the whole main procedure (which will cause the program not to work).

1
2
3
4
5
6
7
8
9
package main

import "core:fmt"

/*
main :: proc() {
    fmt.println("Hellope!)
}
*/

Comments can also be used to document the code and/or to add things, like notes, explanations and reminders. The Odin compiler simply ignores all comments, so you can add as much as you need. We will get back to a more in-depth discussion about comments for the purpose of documenting at a later stage.

A slightly longer program

Let’s write a slightly longer program, without introducing any new concepts. Again, create a new directory

1
2
3
4
5
6
7
8
9
package main

import "core:fmt"

main :: proc() {
    fmt.println("First")
    fmt.println("Second")
    fmt.println("Third")
}

To run this program, type odin run . in your terminal window. If you didn’t type anything wrong, you should see:

$ odin run .
First
Second
Third
$

If you were to run this program a million times, you would always see the output in this order. You would never get Second printed before First or anything like that. This is because the default order of execution is from top to bottom. This may seem very trivial, but several of the concepts we are going to come across going forward exist specifically to change the order of execution, so by keeping in mind that programs execute from top to bottom by default, we can now contrast this against what things like conditionals, loops and calling procedures do.

Also, main is a procedure. We will look much more into what that means later, but just know that the procedure with the name main is special: it is the place where a program starts (the entry point). All programs must have a procedure called main.

Final words

All the programs we have written so far are static. They produce exactly the same result every time you run them. In the next lesson we are going to start working towards being able to write programs that are dynamic, that is, their output can change based on things like user input.

Exercises

Since we haven’t learned all that much yet, the exercises will be quite repetitive. Once you are done, you can check your answers here

Exercise 1

Write a program that prints your name to the terminal.

Exercise 2

Using only what we have learned so far, write a program that prints the numbers 1 to 10, each on a separate line. Think about how the program would look like if I asked you to print out the numbers 1 to 10,000 instead.

Exercise 3

What happens if, instead of fmt.println you write fmt.print in the program below?

1
2
3
4
5
6
7
8
9
package main

import "core:fmt"

main :: proc() {
    fmt.println("Hi there!")
    fmt.println("I am learning Odin")
    fmt.println("It's a lot of fun so far.")
}

Exercise 4

Write a program that prints out the names of all the months of the year, one per line, using only what you have learned in this lesson.

Exercise 5

Fix any errors you can find in this program so that it runs properly.

1
2
3
4
5
6
7
8
package main

import "core:fmt"

main() {
    fmt.println("Odin is a programming languge")
    fmt.println('... for the joy of programming!')
}

Exercise 6

The program below uses a concept we haven’t learned yet. Try the progam and, based on the output, try to reason about what might be happening.

1
2
3
4
5
6
7
8
9
package main

import "core:fmt"

main :: proc() {
    lang := "Odin"

    fmt.printfln("I am currently learning %s", lang)
}

Exercise 7

Is Odin a case-sensitive language? That is, are things like proc and PROC the same or are they two different things? The only way to be certain is to try it out.

Exercise 8

What happens if, instead of main, you call the procedure something else, like start? Give a try and take not of the result.

Exercise 9

Fix any errors in the following program:

1
2
3
4
5
6
7
package main

import "core:fmt"

main :: proc() {
    fmt.PrintLn("Howdy!")
}

Exercise 10

The following program has several errors. Can you find them all?

1
2
3
4
5
6
7
Package main

import "core"

proc :: main() {
    fmt.printn("Welcome to Odin!")
}

Exercise 11

What does the following little program do?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main

import "core:fmt"

main :: proc() {
    a := 5
    b := 3

    fmt.println("a + b =", a+b)
    fmt.println("a - b =", a-b)
    fmt.println("a * b =", a*b)
    fmt.println("a / b =", a/b)
}

Once you have run it, try changing the two numbers (5 and 3) and run it again. Notice how the output changes. What happens if you change the number 3 to a zero?

Exercise 12

What does the following program do?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main

import "core:fmt"

main :: proc() {
    price := 125

    if price > 150 {
        fmt.println("It's too expensive!")
    } else {
        fmt.println("I'll take it.")
    }
}

Try changing the line price := 150 a few times and running the program again. What happens if you set the price to something above 150, like 200? What happens if it you set it to exactly 150? A concept in this program might possibly be new to you, but you can use the output to figure out how the program works.

You are going to learn how to use the if statement already in the next lesson, so take this as a sneak peak into the future.

Exercise 13

What does the following program do?

1
2
3
4
5
6
7
8
9
package main

import "core:fmt"

main :: proc() {
    for i in 1..=10 {
        fmt.println(i)
    }
}

Based on the output you get, could you get it to count from 5 to 20 instead? What happens if you change the 1..=10 to 1..<10? What happens if the first number is greater than the second one, like 10..1

We are going to look into what for is and how to use it very soon. For now, just make some mental notes about what you have noticed about it so far.

Exercise 14

What is the default order of exectution? Write a small Odin program that uses more than a single fmt.println statement and use the default order of execution to explain why you get the output that you get.

Exercise 15

Use single-line omments to prevent the following program from printing out any name that begins with the letter J.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import "core:fmt"

main :: proc() {
    fmt.println("George")
    fmt.println("Abena")
    fmt.println("James")
    fmt.println("Vanessa")
    fmt.println("Jojo")
    fmt.println("Nii Okai")
}

Exercise 16

Use multi-line comments to avoid printing out any of the letters from J to T.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import "core:fmt"

main :: proc() {
    fmt.println("A")
    fmt.println("B")
    fmt.println("C")
    fmt.println("D")
    fmt.println("E")
    fmt.println("F")
    fmt.println("G")
    fmt.println("H")
    fmt.println("I")
    fmt.println("J")
    fmt.println("K")
    fmt.println("L")
    fmt.println("M")
    fmt.println("N")
    fmt.println("O")
    fmt.println("P")
    fmt.println("Q")
    fmt.println("R")
    fmt.println("S")
    fmt.println("T")
    fmt.println("U")
    fmt.println("V")
    fmt.println("X")
    fmt.println("Y")
    fmt.println("Z")
}

Exercise 17

Try the following program. Is its output the same or different from the one in exercise 16?

1
2
3
4
5
6
7
8
9
package main

import "core:fmt"

main :: proc() {
    for r in 'A'..='Z' {
        fmt.println(r)
    }
}

You can use the output to try to figure out how the program works.