Nimrod: A new approach to metaprogramming
nimrod-lang.org
nimrod-lang.org
- clean Pythonic syntax (whitespace relevant but tabs are forbidden)
- native Perl syntax for regular expressions (slide 42)
- subrange types as in Ada
- set types as in Pascal
- strings as case (switch) selectors
- easy C interface with automatic type conversion (only functions as parameters need additional compiler pragmas)
- typed macros (templates)
- object code: native, C, Javascript (probably more to come)
I am working with Nimrod right now, and it is really one of the most productive languages that I ever encountered. It seems to mix the best features of other popular languages. Nimrod actually is where Python should be. I wonder if it is suitable for small embedded systems also.
By the way, one important difference to Perl regular expressions is that re"..." always parses the whole expression where Perl parses partially. Fortunately Perl's behavior can easily be simulated with a template.
A simple word counting script I just wrote compiles down to about 52k on 64bit OS X.
Edit: Apparenetly not...there are alot more modes in there but the UI exposing them is easy to miss
I guess you meant "what I wanted Python to be".
I don't see how Nimrod is a natural evolution of Python. Static types and meta-programming by templates are far from anything Python proposes. I believe not even the syntax comparison applies too much, it's syntax is more reminiscent of Pascal than Python itself.
Cool! Is what you're working on public?
Also, Nimrod has a very nice library. Definitely has enough "batteries" in it to get started.
http://nimrod-lang.org/lib.html
Just a few impressive ones: http client, server, json parsing, actor support, redis db driver, zmq, cairo graphics, OpenGL wrappers, even Lua and Python support.
That looks very appealing, anyone using, what is your experience with it?
If you want to do some serious experimentation with Nimrod, I recommend using 0.9.3 (the Github version). It is considerably more mature and stable than 0.9.2.
The one oddity that I'm still getting used to is Nimrod's preference for value types. I.e., the string and seq[T] types use copying for assignment [1] by default, when most other languages assume reference semantics (you can use reference assignment instead, but have to say so explicitly). This may create inadvertent overhead if you are unaware of it, but also avoids some pitfalls you otherwise may run into with mutable strings.
As for the default GC, it's not that you can actually guarantee a maximum pause time [2]. The GC uses deferred reference counting (i.e., eliding most RC operations and batching the ones that are needed). As long as your data structures are acyclic, that allows for a very low upper bound on GC pause times. Pause times for dealing with cyclic structures depend on the size of the cycles involved (and the size of data structures attached to those cycles). A practical workaround for when you have to deal extensively with cyclic data structures is to make use of the fact that each thread has its own heap: thus, putting all time-critical stuff in one thread where cyclic data structures aren't used, and the rest in another thread.
[1] Copying is not used for passing arguments to a procedure or for returning a result, only actual assignment.
[2] You can influence it to some extent by changing the value of ZctThreshold in system/gc.nim, which specifies the size of the zero count table. Each GC iteration will still have to scan the stack, of course.
Edit: Oops, to correct myself, Nimrod does actually have a GC_setMaxPause() procedure, though I still don't think it can guarantee hard upper bounds on pause times.
Could you elaborate if possible a bit on a thread private heap. I know Erlang's actor and Dart's isolates allow that (which makes it easy for it to implement a concurrency GC).
What is the mechanism for creating private heaps (if there is one)? Or is it just by convention as in "just know that from this one thread I only create objects and no other thread will access it"?
Note that you can also fall back to GC-free allocation with untraced references (using ptr instead of ref) but will then have to manage that part of the memory yourself (i.e., deallocate untraced objects yourself).
The technique is called "trial deletion" and only has to traverse potential cycles. Strictly speaking, a type-agnostic implementation may have to traverse all objects reachable from an object whose reference count was decremented since the previous pass, but in a strongly typed language you can skip that for all objects that can't be part of a cycle. Nimrod at least makes use of that information in asgnRefNoCycle() in system/gc.nim.
Obviously, if everything on the heap is part of one big cycle, then, yes, you'll have to scan the entire heap.
Looks like a cross-platform language thats an even more acceptable lisp than ruby (hello macros!), with multiple build-language targets including C/javascript/C++ and a fast garbage collector? Like Go, but even cooler?
https://github.com/nimrod-code/Aporia/issues/37#ref-issue-17...
As a rule, I avoid any project where the developers have too much of the it-doesn't-work-and-I-don't-care attitude, mainly because you can't build on top of a foundation that isn't maintained fastidiously--you'll waste all your time fixing the foundation and won't get productive work done. Culture matters.
They should note what some of the OpenDylan folks are doing and write a plugin for Intellij.
Not quite. What you save with deferred reference counting is what is generally the biggest cost of reference counting: assigning references to local variables and having local variables go out of scope. Deferred reference counting only requires an RC update if you store a reference in a heap object or in a global variable.
You will, of course, necessarily incur the overhead for allocation and deallocation, which one can make cheaper (bump allocation in generational and copying GC, memory regions) but can't entirely get rid of, especially in non-copying/compacting schemes.
Cycle detection primarily affects pause time, not overhead.
Furthermore, the RC updates needed for DRC have to be thread-safe in a concurrent scenario. I understand that Nimrod has chosen not to have a thread-safe GC, but I don't think that'll scale for systems programming: too many algorithms want shared memory, and manual memory management is much more difficult in a concurrent setting. Once you go thread-safe, RC updates become extremely expensive, while concurrent GC is well-studied and performant.
This is simply false. In fact, concurrent versions of deferred reference counting have been known and studied for years [1]. The simple solution is to store the RC updates in a buffer and execute them only during a collection phase.
Pause time is a form of overhead. It reduces both latency and throughput.
Yes, but for many applications (e.g., HPC) only amortized cost is relevant.
Note also that you can do cycle detection concurrently with the mutator's operation (again, see [1]). Concurrent cycle detection makes the implementation more complicated, but no more so than a concurrent tracing scheme. Moreover, if your program is indeed performance-critical, RC schemes allow you to minimize the impact on cycle detection by designing your code so as to avoid cycles (either by using acyclic data structures exclusively or by using weak pointers). Conversely, tracing schemes make it difficult to programmatically influence worst case pause time.
[1] E.g., http://researcher.watson.ibm.com/researcher/files/us-bacon/B...
I disagree—it's much more complicated. Concurrent GC is not trivial, but it doesn't have seven different colors and two different tests (sigma and delta test).
A good concurrent reference counting system is just as complex as a good tracing garbage collector, because it requires the same runtime machinery—precise stack maps, write barriers, etc., to perform backup tracing. But it also has the reference counts to deal with. It ends up being more complex overall.
> Moreover, if your program is indeed performance-critical, RC schemes allow you to minimize the impact on cycle detection by designing your code so as to avoid cycles (either by using acyclic data structures exclusively or by using weak pointers).
No, that's my point—even if you use acyclic data structures, there is no guarantee that you won't have the CC run because you had multiple references to an object and you dropped one, making the cycle collector suspect it was part of a cycle. This is the entire reason why ForgetSkippable was added to Firefox: this happened a lot in practice. The solution was to add a bunch of ad-hoc code to make the cycle collector drop objects from the purple buffer, much like the "acyclic" pragma does in Nimrod—but now you have the possibility of leaks unless this is done very carefully.
> Conversely, tracing schemes make it difficult to programmatically influence worst case pause time.
In collectors like Metronome, it's extremely easy: set the pause time to what you want it to be. That's the only solution that's really scalable in my view: working around the collector by manually telling the CC not to scan certain types feels too error-prone.
How does dynamic typing work in Nimrod, if it has it? What's the equivalent of being able to call Write() on any io.Writer in Go, for example? [Edit: just found the explanation at http://nimrod-lang.org/tut2.html#dynamic-dispatch but have not yet read and digested.]
I'd love to see some open-source projects that've been written in it--the Nimrod tools and stdlib are obviously a good start. I think one of the things that really helped Go was having lots of n00b-friendly content (the tour, a short "spec", Effective Go doc, blog posts, talks); you could call it "marketing", but it really helped me, at least.
Why can't people find original names for software? :(
My only complaint is that my internal Python (awesome) vs. JavaScript (not so awesome but becoming standard) war gets tackled from a third side now. Another language to care about - not exactly what I needed.
Having said that: Nimrod looks beautiful and maybe it's time to hop on the bandwagon.
Original site with almost same description verbiage: https://web.archive.org/web/20110704041631/http://force7.de/...