3 ms·
Something I find quite interesting about Nim is write tracking: http://nim-lang.org/blog/writetracking.html http://nim-lang.org/blog/writetracking.html. It uses
by logicchains 12y ago
Something I find quite interesting about Nim is write tracking: http://nim-lang.org/blog/writetracking.html http://nim-lang.org/blog/writetracking.html. It uses the language's effect system, and allows not only specifying for instance that a function is referentially transparent, but also specifying how an impure function accesses or modifies global state.
An example from the above link:
var gId = 0
proc genId(): natural {.writes: [gId].} =
gId += 1
return gId
To quote the article: "Here the effect systems shows its strength: Imagine there was a genId2 that writes to some other global variable; then genId and genId2 can be executed in parallel even though they are not free of side effects!"
The effect system can also be used for exception tracking, specifying what kind of exceptions are function may throw. It can moreover be extended to work with user-defined effects.
- chipsy 12y agoA lot of features in Nim show a similar kind of designed pragmatism. It's big, and has a lot of stuff that you just won't use in everyday situations, but the uncommon features tend to hit really specific engineering problems that do come up in the real world. I like it a lot better than what I see coming out of Rust, at least at this moment.
- vanderZwan 12y agoOut of curiosity: why is it hard for compilers to keep track of this automatically? At least, my gut feeling says that if it had been easy to do, this would be a solved design problem in newly developed languages by now - at least the statically compiled ones like Nim.
- uhno 12y agoFor simple cases (such as the example in the GP comment) a compiler can easily infer those annotations. Complications are introduced in languages which allow aliasing. Precise alias analysis has been shown to be NP-hard [1] (as are many other compiler problems), and thus in general compilers must make very pessimistic assumptions to avoid making incorrect optimizations, such as allowing two functions to execute in parallel. Other issues crop up due to the open-world assumption. This is especially true in the presence of separate compilation when trying to reason about global behavior. Example: does function f() in file f.c modify global variable g in file g.c? The compiler may not be able to prove that one way or another at compile-time (consider if file f.c was already compiled to object code f.o, and only g.c was being recompiled), and so it must assume that f() may modify g. This particular example can be solved with link-time optimization, but you get the idea of how complicated the real world can get. [1] Horwitz, "Precise flow-insensitive may-alias analysis is NP-hard," TOPLAS 1997.