Nim is a programming language with an optimized ratio of programmer productivity and system performance. Its narrow focus on performant code makes Nim-written programs runnable on low end mobile phones and IoT devices which makes the language an ideal tool for making software available to third and 2.5th world countries.
Nim is the language behind Nimbus – the light Ethereum node built by Status. The aim of Nimbus is to let people run a sharding node of Ethereum on low end devices, thus increasing the network’s decentralization even further.
This is the first in a series of Nim tutorials. No prerequisites or previous programming experience is required to follow along.
Installation and basics
I recommend you use
choosenim to install and use Nim. Choosenim is a tool which lets you use multiple version of Nim on the same operating system. This lets you follow along with outdated tutorials and books by switching to an older version, and also lets you run Nim programs written in a version different from the one you have installed.
On Windows, you can install choosenim by downloading a release from the releases page. On a Unix environment like OS X or Linux, you can just run the command below and follow instructions:
curl https://nim-lang.org/choosenim/init.sh -sSf | sh
After installation, the newest stable version of Nim will be automatically activated. If you’d like to change the version used, the command to use is this one:
For developing in Nim, I recommend the free Microsoft Visual Studio Code with the Nim addon (go to addons and search for Nim).
The first program any new programming language trainee writes is a Hello World program.
Note: in some code examples below, you’ll see the
# symbol. This indicates a comment, and all content to the right of it on a single line will be ignored. This is useful for leaving notes to other programmers.
In a folder where your Nim code will reside, make a subfolder for this tutorial and create a file called
helloworld.nim with the content:
echo "Hello World"
echo command outputs a value on the screen. In this case, the value is
Hello World which needs to be surrounded by quotes because we’re dealing with a type of data called “string” – a mixed set of letters, numbers and/or symbols. Strings always come in quotes.
Read this post if you’re curious about why a string is called a string
To run this program, in the folder where it’s located (get there by running the Terminal in OS X / Linux or Powershell, Git Bash, Console or similar on Windows) run:
nim c -r helloworld.nim
The output should look like this:
Hint: used config file '/Users/swader/.choosenim/toolchains/nim-0.19.0/config/nim.cfg' [Conf] Hint: system [Processing] Hint: helloworld [Processing] CC: helloworld CC: stdlib_system Hint: [Link] Hint: operation successful (12267 lines compiled; 0.874 sec total; 16.414MiB peakmem; Debug Build) [SuccessX] Hint: /Users/swader/nim/tutorial1/helloworld [Exec] Hello World Brunos-MacBook-Pro:tutorial1 swader$ ls helloworld helloworld.nim Brunos-MacBook-Pro:tutorial1 swader$ ./helloworld Hello World
The example above is executed on the OS X operating system, but the output will be similar if not identical on all others.
Let’s explain the above command:
cmeans “compile”. This means that the
-rmeans “also run after compilation”. The compiled program will be located in the same folder after compilation and can later be run with
./helloworldon OS X or equivalent on other systems:
If we leave out the
-r from the command, the program will only be compiled and placed in the folder, not run. You can run it manually.
Like any other programming language, Nim also supports variables. Variables are “boxes” into which values can be stored for later use.
Given that Nim is a statically typed language, we need to define the type of each variable as we declare it.
var myVar:string = "Hello World" var myNum = 5;
In the above example, the word
var means “declare a variable”.
myVar is the name of the variable while
:string marks its type – in this case that’s
string. On the right side, there’s the value of this variable: “Hello World”. The second line demonstrates implied types – Nim understands from the declaration that it’s dealing with an integer and concludes that it’s an integer type, so declaring the type isn’t necessary. Still, for the sake of standardization and readability, we recommend you always use types.
Let’s redo our program to use variables.
var msg:string = "Hello World" echo msg
If we recompile the program, the output should be the same as it was before.
A variable’s type must remain the same throughout the lifetime of a program, but its value can change.
var name:string = "Bruno" name = "Bitfalls" # OK name = "B" # OK name = "" # OK name = 5 # ERROR
A variable of type string cannot become an integer but can obtain the value of a numeric string:
name = "5" # OK
To make the program at least somewhat useful, we need to be able to accept user input. We can use the
readLine function for this and pass it the input from
stdin – the “standard input” – the user’s terminal.
readLine can be used to read web based input or even read files, but in this case we use it to read user input.
var msg:string = "Hello" echo "Enter name:" var name:string = readLine(stdin) echo msg & " " & name
In the code above we first define a variable called
msg which has the value “Hello”. Then, we tell the user that we expect their name: “Enter name”. After that we declare another variable
name which is a string but for its value we set the user input via
readLine and the argument
stdin. In other words, we assign to this variable anything that the user puts in and then presses Enter. Finally, we output the greeting by combining the strings using
$ nim c -r helloworld Hint: used config file '/Users/swader/.choosenim/toolchains/nim-0.19.0/config/nim.cfg' [Conf] Hint: system [Processing] Hint: helloworld [Processing] Hint: [Link] Hint: operation successful (12270 lines compiled; 0.587 sec total; 16.418MiB peakmem; Debug Build) [SuccessX] Hint: /Users/swader/nim/tutorial1/helloworld [Exec] Enter name: Bruno Hello Bruno
Combining strings with
& leaves both strings intact and only returns their combination. Alternatively, we can use the
add function present on every string to add a new string to its end and permanently alter it.
This method is different from
& in that it changes the operands – the string being added to will be changed to the result of the adding. Therefore, calling this function twice would add the suffix twice, like so:
var foo:string = "foo" var bar:string = "bar" echo foo & bar # "foobar" echo foo & bar # "foobar" var foobar:string = foo & bar echo foobar # "foobar" echo foo.add(bar) # "foobar" echo foo.add(bar) # "foobarbar"
Var, let, const
There are two more ways to declare variables:
const. Both are used to declare immutable values, with one key difference: the value of a
const needs to be known at compile time, while the value of
let does not and can be filled during execution of the program, but cannot be modified afterwards.
Out Hello World program can thus be improved like so:
const msg:string = "Hello" echo "Enter name:" let name:string = readLine(stdin) echo msg & " " & name
msg is the value which will never change – we’ll always want to say hello. Given that the name is also only read once, it’s fair to declare it as immutable, but we don’t know its value at compile time so
let is the right choice here.
Generally, you’ll use
let more often than
const. Because it can lead to code security and performance boosts, it is recommended you use
let whenever you can rather than
var, unless you’re certain that the
var’s value will have to change.
In this tutorial, we covered the basics of the Nim language – variables, declarations, input and output and compilation. In the next one we’ll explain Nim data types and prepare the foundation for learning about functions and loops.