Nim Adventures
2014-07-13
· Nim
· Programming
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:
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
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
const
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" ] :
langs . add ( l [ "title" ] . str . split ( "Category:" ) [ 1 ] )
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
proc printf ( formatstr : cstring ) {. header : "<stdio.h>" , varargs .}
var x = "foo"
printf ( "Hello %d %s! \n " , 12 , x )
when defined ( windows ):
const imglib = "imglib.dll"
elif defined ( macosx ):
const imglib = "imglib.dylib"
else :
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