• msd@infoserv.dk
  • +45 21402120
  • Go right

From Go to Nim

I have been using Go to build small project for a while, and I'm now looking into Nim.

Coming from Go to Nim gives certain challenges.

  • Go compiles directly to a binary. Nim compiles to c/c++ and depend on a c-compiler to compile to binary.
  • Go used { } to define blocks of code. Nim uses indention to define blocks og code, like Python.
  • In Go there are one primary terminal command go to manage packages, compile and run your project. Nim has nim for compilation and nimble for package management.
  • go.mod is in Nim called projectname.nimble.
  • go get both download a library and add this library to the local go.mod file. Using nimble install, Nimble downloades a library, but you must manually add the library to the local .nimble file to be able to use it in the project.
  • Go usually has few ways to do something and Nim seems to have many ways to do the same thing, making the code less readable:
    • parentheses can be omitted
    • method can be called with obj.method(x) or method(obj,x)

Go does not warn about modifying content in methods. If the method has a pointer receiver it works, if not, its just changes in the local copy and discarded when the method ends.

Lets Nimble

Nim's package manager is called Nimble.

Start a new project:

nimble init helloworld

Install a package:

nimble install illwill
nimble install illwill head
nimble install https://github.com/johnnovak/illwill

Alert: Remember to manually add the package, fx illwill to the projects projectname.nimble file in the root, fx:

# Dependencies
requires nim >= 1.6.10
requires illwill

To build or run:

nimble build
nimble run

Ofcouse nimble can do a lot more that this.

nimble refresh
nimble search illwill

Leetspeak Nim

Yes, Leetspeak was a thing...

This code shows som string mangling and access to argv command line items.

import std/strutils
import std/os

proc leetspeak(s: string): string =
  let r = s.toUpper()
  const leetfabet = [("E","3"), ("B","8"), ("C","["), ("L","1"), ("O","0"), ("A","4")]
  return r.multiReplace( leetfabet )

proc main() =
  for i in countup(1,paramCount()):
    if i>1:
      stdout.write " "
    stdout.write leetspeak(paramStr(i))
  stdout.write "\n"
  stdout.flushFile()

when isMainModule:
  main()

Compile and run with:

nim c -r leet.nim Hello World

Trying out Nim

Even though it has little adoptation, Nim looks like a cool promissing language! Lets try it out.

Getting started is easy, using choosenim

curl https://nim-lang.org/choosenim/init.sh -sSf | sh

After answering a few questions, you have Nim installed and can call:

nim -v

Hello World

Nim's package manager is called Nimble. Lets use it:

nimble init helloworld

Select "Binary" as "package type".

Nimble will now create a new folder called helloworld. The folder contains a file called helloworld.nimble which describes the new projects dependencies.

A simple hello world program is places in src/hello.nim it looks like this:

# This is just an example to get you started. A typical binary package
# uses this file as the main entry point of the application.
when isMainModule:
   echo("Hello, World!")

Like Python, Nim use whitespace (spaces, not tabs) indentation to indicate scoope. No {} is used.

To compile the program, write:

nim c src/hello.nim

or, to compile and run:

nim c -r src/hello.nim

or for projects, you ban use Nimble to build the project:

nimble build

To view the c source of your Nim program, try:

mkdir cache
nim c --nimcache=cache src/hello.nim

Now you can find the c source in the cache folder.

A bit more hello world.

import std/strutils

proc main() =
  let s = "Hello, World!"
  for c in s: # iterate chars in string
    if c=='o': # replace o with 0
      stdout.write "0"
    else:
      stdout.write c
  stdout.write "\n"
  stdout.flushFile()

when isMainModule:
  main()