I've been using Nim for a few months now and really like it. I've been using Python for the past 10+ years and love it, but its very low performance is starting to become a problem. I learned Go a couple of years ago and while I like it, especially the performance/concurrency, I'm not nearly as productive with it as I am with Python. I found Nim very easy to learn (with the exception of templates and macros), and love the flexibility of UFCS and the performance.
Nim's ecosystem is still relatively small and can't compete with Python's depth and breadth of third party modules and frameworks. Most Python programmers won't be able to switch to Nim but it can be used as a companion language to help with performance problems. Writing binary extension modules with Nim is much more approachable for the average Python programmer than attempting the same in C/C++. I've posted the following article about leveraging Nim to speed up Python:
https://robert-mcdermott.gitlab.io/posts/speeding-up-python-with-nim/
I've also posted this article to HN for discussion (hopefully) purposes: https://news.ycombinator.com/item?id=18964080
Hopefully this will result in some Python programmers to take a look, or second look at Nim.
That is an interesting article,but I think using such a toy fibonacci function is some sort of cheating and may lead to misleading results.
For problems with a few number of basic input data (ints, floats, chars) and similar output it is always easy to find C code which does exactly that task and then call that routine from whatever programming language we are using.
But generally we are dealing with objects and complicated data structures build by these objects, so we have to create the objects, work with it, store it in not always trivial containers, and finally release memory.
Years ago I tried using CGAL and Boost libs from Ruby for data structures like 2D triangulations, RTees or for priority queues. In both cases we have to work with objects and to access them from inside the C/C++ lib as well as from Ruby. And for the triangulation one more problem is, that there is not only a linear container with our objects, but we have the triangulation, which contains Vertices, Faces, neighbor relations and much more.
I managed to call CGAL from Ruby, but it was not very easy and it was not very efficient.
I can not really believe that using Nim from Python is that easy for such use cases, I would even assume that Nim may make it more difficult than C/C++ as Nim has its own GC which may interfere with Pythons own Garbage Collector. Maybe I am wrong -- would be great.
For me the great advantage of modern languages like Nim, Crystal, Go, Julia, maybe Rust and some more is that we do not have to mix more than one languages to get high speed from high level code.
I can not really believe that using Nim from Python is that easy for such use cases, I would even assume that Nim may make it more difficult than C/C++ as Nim has its own GC which may interfere with Pythons own Garbage Collector. Maybe I am wrong -- would be great.
There is good news, you are wrong. ;-) The full Nim language can be used with --gc:regions (No, that is not a subset). There is also bad news, it's still actively developed and hardly documented. :-) It also has its own disadvantages, but what hasn't.
The full Nim language can be used with --gc:regions
For a while the language manual mentioned user defined regions, and now that section is gone. IIRC I asked before about this and you'd said that the user defined region stuff would be subsumed by destructors. Does my recollection agree with yours, and if so, is that still the plan?
It would be great if there were a doc comparing regions and destructors in Nim; as a sometime C++ programmer regions are not quite the same as C++ RAII (destructors?) and I may want both.
[quote]Nim's ecosystem is still relatively small and can't compete with Python's depth and breadth of third party modules and frameworks. Most Python programmers won't be able to switch to Nim but it can be used as a companion language to help with performance problems.[/quote]
To be honest, I'm looking for newlanguages with small eco systems to teach programming. At the begnining, there was Pascal, then it has been let down for Java, but the pure OO aspect we passed to Python, but it started to becomehuge and complicated so we are looking for another option.
Maybe we should mention that we can also accelerate Ruby with Nim -- I just found the link to a nice blog post in my bookmark list. I am not sure if that example code still compiles with latest Nim compiler, but the blog post was nice to read and even shows how to use parallel Nim code:
http://bootstrap.me.uk/programming-languages/2017/07/09/nim-for-the-discerning-rubyist.html
I know it's not the main point of this article, but use of recursion kinda dulls the excitement of "Speeding Up Python with Nim". Why not show the fastest fib version, with a loop?
This runs many orders of magnitude faster. It also works for n>92 (int64 overflow). Pre-filling an initial sequence at compile time fully compensates for the bigint performance hit relative to int64.
import os, bigints, nimpy, times, strutils
proc fibPrefill(max: int): seq[BigInt] =
echo "Pre-calculating cache..."
result = @[1.initBigInt, 1.initBigInt]
for pos in 2 .. max:
result.add(result[pos-1] + result[pos-2])
const fibCacheStarter = fibPrefill(1000)
var fibCache = fibCacheStarter
proc fib(n: int): string {.exportpy.} =
if n < 1: return "0"
let startPos = fibCache.len
let endPos = n - 1
for pos in startPos .. endPos:
fibCache.add(fibCache[pos-1] + fibCache[pos-2])
return $fibCache[endPos]
proc fibVerbose(n: int) {.exportpy.} =
echo "Calculating for fib($1)..." % $n
let start = cpuTime()
let res = fib(n)
let elapsedNs = int((cpuTime() - start) * 1_000_000_000)
let elapsed = initDuration(nanoseconds = elapsedNs)
echo " => $1 (in $2)\n" % [res, $elapsed]
# when isMainModule:
# if paramCount() == 0:
# fibVerbose 100
# else:
# for paramStr in commandLineParams():
# fibVerbose paramStr.parseInt
Next step would be to figure out how to return Python's long number instead of a string...
If you want to actually calculate Fibonacci numbers not use it as a (poor) benchmark for funcalls/recursive overheads or for other purposes, then you may also find this interesting: https://sahandsaba.com/five-ways-to-calculate-fibonacci-numbers-with-python-code.html
In terms of the closed form formula, it would be nice if someone wrapped mpfr or similar someday for a bigfloats.