HookRace Blog     Posts     Feed     DDNet     Me

Nim Adventures

To learn some Nim I held a talk about it at the GPN14 (in German, Slides).

Afterwards I started solving Rosetta Code tasks in Nim to get a better feel for the language and standard library. That also made me discover some rough edges in the language, but luckily the community, albeit small, is active and competent. All the small code pieces I wrote are now on Github too.

What I noticed is that most problems are as easy to solve as in Python, but much more performant. I'm now more confident that this language is the right choice for writing HookRace in.

Some highlights:

Insertion Sort

Once in Python:

def insertion_sort(l):
    for i in xrange(1, len(l)):
        j = i-1 
        key = l[i]
        while (l[j] > key) and (j >= 0):
           l[j+1] = l[j]
           j -= 1
        l[j+1] = key

and in Nim:

proc insertSort[T](a: var openarray[T]) =
  for i in 1 .. <a.len:
    let value = a[i]
    var j = i
    while j > 0 and value < a[j-1]:
      a[j] = a[j-1]
      dec j
    a[j] = value

Rank languages by popularity

The standard library is extremely useful, providing an HTTP client, JSON parser, regular expressions, string utils and algorithms, which I use to create a ranking of the popularity of languages on Rosetta Code:

import httpclient, json, re, strutils, algorithm, future

  langSite = "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json"
  catSize = "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000"
let regex = re"title=""Category:(.*?)"">.+?</a>.*\((.*) members\)"

var langs = newSeq[string]()
for l in parseJson(getContent(langSite))["query"]["categorymembers"]:

var ranks = newSeq[tuple[lang: string, count: int]]()
for line in getContent(catSize).findAll(regex):
  let lang = line.replacef(regex, "$1")
  if lang in langs:
    let count = parseInt(line.replacef(regex, "$2").strip())
    ranks.add((lang, count))

ranks.sort((x, y) => cmp[int](y.count, x.count))
for i, l in ranks:
  echo align($(i+1), 3), align($l.count, 5), " - ", l.lang

Calling a C function

proc printf(formatstr: cstring) {.header: "<stdio.h>", varargs.}

var x = "foo"
printf("Hello %d %s!\n", 12, x)

Wrapping a shared C library

when defined(windows):
  const imglib = "imglib.dll"
elif defined(macosx):
  const imglib = "imglib.dylib"
  const imglib = "imglib.so"

proc openimage(s: cstring): cint {.importc, dynlib: imglib.}

echo openimage("foo")


A quine is a program that prints its own source code. This Nim program does that once at compiletime and once at runtime:

const x = "const x = |const y = x[0..9]&34.chr&x&34.chr&10.chr&x[11..100]&10.chr&x[102..115]&10.chr&x[117 .. -1]|static: echo y|echo y"
const y = x[0..9]&34.chr&x&34.chr&10.chr&x[11..100]&10.chr&x[102..115]&10.chr&x[117 .. -1]
static: echo y
echo y