While I rather like nim as a language, there's a few more cons that need to be considered for any real use of the language:
- It has a bus/lottery factor of 1. The vast majority of all the changes were done by Araq and I have very little faith that the language would survive without him. This is even more pronounced with Zig (mentioned in comments here).
- It has had some very embarrassing bugs after the 1.0 milestone. Most of them were specific to Windows (e.g. [0]), which casts a lot of doubt on its cross-platform promise. Multiple times in the last year, when debugging a nim program, it turned out that the problem was in the language/standard library.
Now, these might not be reasons enough to not use nim, since it's a lovely language when it works, but a pro/con list should be honest.
While Araq is BDFL and is still doing most of the implementation for Nim, there are nontrivial contributions from others, and commercial sponsorship at this point.
And with respect to the ecosystem-at-large, there are tens of contributors and a very healthy package repository: nimble (package manager) written and maintained by dom96; arraymancer (tensor+array+nn) written and maintained by mratsim; an up-and-coming thread runtime by mratsim (called weave) which is better than just about any existing thread runtime for any language. NimPy for seamless python integration (... which produces one DLL that works with every Python version; can your C++ do that?) by yglukov, and many more.
And most libraries you'd need already have a Nim wrapper, (and one is extremely easy to generate if not), though the pure-nim body is growing every day - have a look at https://nimble.directory/
I see one of the top jobs of the dictator as exercising reputation and credibility to gather and delegate expert work to expert lieutenants. If the years pass and you're still the lonely dictator...
What was Rusts early years like? Was it one developer for the first part?
I'd imagine this is not a big deal in the early days, where the benevolent dictator is as much the language as the project itself, not all technology adoption happens on the same timelines. Matz with Ruby took a long time to become super popular, Rich Hickey with Clojure seemed to be a powerhouse even as that found quick adoption before stalling.
When Rust 1.0 was released it had in the order of hundreds of developers doing work here and there.
When Rust started as a hobby project it was a one man effort, but it was also a project with ~1 user. It grew developers before actually growing users, and for a while, it had more developers than users.
Rust is design by committee with complicated and large syntax area and to solve one problem of memory safety created a mountain of borrow checker syntax and a steep learning curve.
So only time will tell if BDFL based language comes up like Linux or design by committee like language. Right now Rust is not that significant like Nim and Zig so all have a chance to come up.
Once there are substantial software written in them like C or C++ than only will know, right now among modern language only golang and Swift reached that stages as being significant systems programming language in spite of GC. Indeed I doubt if Rust will be as revolutionary as Lisp or Haskell or Smalltalk in terms of contributions for the development of compilers and language designs.
> What was Rusts early years like? Was it one developer for the first part?
In the very beginning, it was a one-man project, but after some time it was picked-up by Mozilla research as an official research project, with several developers working on it (brson and pcwalton in addition to the language creator) and they also started a research new browser (in partnership with Samsung) using this experimental language. That's when people started to hear about Rust (and it was still very far from 1.0 at this point).
Certainly. And I hope same thing happens with nim. All I'm advising against is people betting their livelihood on nim reaching critical mass before a single unexpected event happens that removes the benevolent dictator from the picture. Or at very least be aware of it and make an informed decision.
While the lottery factor is concerning, also many corporate-driven languages have a similar risk: the company can drop the language or bend it out of shape to satisfy business needs. It happened many times.
> Most of them were specific to Windows, which casts a lot of doubt on its cross-platform promise.
Oh. That really surprised me, as I had assumed the bugbears I have as an occasional nim user were because it was developed for/on Windows primarily. Actually bothering to take a look seems to show me that isn't the case at all.
Bugbears such as the linking story on Linux¹, the argument handling², the style and verbosity of the compiler output, [a bunch of others]. Nothing show stopping to be fair, but a bunch of things that just seem out of place(and that always seem to require explanation when co-workers see a nim tool).
Does anyone know the interpretation/etymology of 'lottery factor'? I assume it's the risk of the Key Person winning the lottery and abandoning the project? I guess it makes more sense in the context of rank-and-file employees, rather than passion projects...
I assume it only applies in the cases where the project is being produced by a company, and the lottery winner would then retire. For a hobby project, Key Person winning the lottery and quitting their day job would be a good thing.
2. The new version of the garbage collector understands move semantics to optimize its reference counting so unlike Rust where you have to deal with it yourself Nim will handle it for you at the expense of a reasonable amount of memory. https://youtu.be/yA32Wxl59wo?t=855 Watch the whole video for more context if you care.
I think it's a really nice language, too many pragmas but still really nice.
I love Nim as a language. I do not love the Nim ecosystem. It is too sparse. Even now there isn't a good web framework that folks can use in production. Jester is ok but it doesnt inspires the same kind of confidence that Echo, Fiber etc would do. Jester still doesnt have its own web page marketing it.
I really think that the folks behind Nim need to focus on getting some killer apps in the ecosystem and in marketing them. That's all Nim needs. Just some useful tools wrapped in a nice package.
It occurs to me that the although they were aimed at different uses cases the language that's actually closest to Nim today is Julia. Python-like syntax, compiled to native code, significant meta-programming capabilities, some native support for concurrency. The biggest difference seems to be the approach to types, since Julia is a dynamically typed language (with optional type annotations) and Nim is statically typed, but Julia's type systems is powerful enough that in practice the difference may not be so big.
Anyone out there who has used both and has more observations?
Julia's ahead-of-time compilation story is not great. If you just want a single executable, it's kind of a pain, and there are all sorts of caveats. I think it's slowly getting better, though, but the language really wasn't designed for that use case. If I needed run-time metaprogramming/JIT compilation/a REPL, I'd go for Julia. For a single executable, I'd choose Nim.
I have another use-case; first-class (easier-than-others?) cross-compilation support.
I had to build a one-off tool that was a a glorified "curl wrapper" with validations, for Windows; on a Mac. Wrote a simple nim script, cross-compiled for Windows, and it's been fine and dandy for a year now :)
I'm sure other languages support this (golang?), but Google's SEO suggested nim-lang.org
This, for sure. For my work I wrote a dynamic library in Nim. The library is loaded by an application written in C, and I needed it to work on both Windows and Linux (Windows for customers, Linux for myself and the server back-end). Setting up a Docker container that runs the entire build and integrates well into the existing build-system we had was fairly straight forward. All Nim needs to cross-compile is a C compiler that can do it (in my case that was MinGW). So now I'm happily running the same Nim dynamic library compiled to both a DLL and a .so.
Yes, it's compiled into two different libraries. Nim hasn't magically made cross-platform dynamic libraries. But the code for both libraries is the same, just compiled for two different platforms.
Also interfacing with C and Javascript libraries is as easy as it gets. Do you need a .dll/.so/.dyn? No problem, the same Nim code will deals with it in a few and clear lines.
I agree with most of the OP's shortcomings. Cross compilation hasn't been a huge problem for me, pretty easy to pull off. But they've been looking into using zig as a cross compiler. Kind of confused as to the current status of the effort though . https://github.com/nim-lang/Nim/pull/13757
Carp also has open pull request for using zig as a cross compiler FWIW
I'm a big fan of Nim, but I really wish it supported cyclic type declarations in separate files and out-of-order functions without forward declarations. As it is, I'm constantly structuring things around those limitations. Big projects often end up squeezed into a single huge file (or a few huge files).
consider `include` instead of `import` if you want to break things down to smaller files.
Also, I'm with Araq on this one -- in my experience, every time I reached for a cyclic-cross-file-type-declaration, there was a much simpler acyclic solution I found later.
Include doesn't work for cyclic types, they need to be in the same "type" block. I do not agree with Araq's stance here, there are often cases when closely-related types need to reference each other, and it's not always convenient to put them in the same file. That's why you see the "types.nim" file in larger Nim projects -- no one has a good solution and just shoves them all together. And, if you use types.nim, you no longer have proper visibility control, since fields cannot be private and there is no package-level visibility. Most languages understand this, C/C++/Rust all allow at least the ability to forward declare a type (and Rust allows cyclic, out-of-order types).
The thing that put me off was the allowed inconsistent name formatting: snake_case, pascalCase, (and is it case-insensitive too). This makes it hard for text editors to find all references besides feeling like you're reading multiple codebases.
This feature is meant to make linking easier but it shouldn't have leaked into variability of a single module's sources.
I really like Nim and have been eager to try for a project -- though for anything other than a simple script/wrapper I'd really want to see source-level debugging support in VSCode for one or two of the backends.
Neverwinter Nights nwsync tools are written in Nim and the source is available to tinker with. I've compiled and used the tools on my FreeBSD box to break apart the modules and prepare them for nwsync distribution (nwsync is used for client/server asset management mostly for persistent worlds, but is handy for just running a one-off server with your buddies).
Now you can learn a bit about Nim and have fun doing it :)
Nim has actually decent type-system with support for algebraic data types and generics. Moreover, Nim is a much higher level language and doesn't sacrifice performance to do it.
In short, while Go has deliberately shunned all modern developments in PL design, Nim has embraced them. Also Nim has real macros, while Go does not.
It's clear to me that though immature, Nim is a much better and more expressive language than Go.
Nim has thread support natively. And an async implementation in it's standard library which is made entirely as a library, so you're free to write your own, in fact there exists alternative implementations of async/await in Nim. Just the fact that a feature like this _can_ be implemented as a library is a testament to how powerful of a language Nim is.
It's far from perfect but it does work (and has for a few years), and it helps you by requiring proof that actions are disjoint. There is work now on including Z3 which would work this much smarter.
I'm not familiar enough with Kotlin to give a real answer, but from what I do know the following might be relevant:
* Backends: Nim compiles to JS both directly, and indirectly (emscripten) with various trade-offs (e.g. 64 bit ints require emscripten). It also compiles to C, C++ and Objective C giving you the simplest most efficient FFI to those languages one can hope for (including e.g. exception handling) while at the same time addressing the largest set of platforms (got a C compiler? you can use Nim). And you also have (almost but not yet quite production quality) native code compiler NLVM. What's the platform range of Kotlin's AOT?
* Metaprogramming: Nim's metaprogramming ability is second only to Lisp[0], I think, and only because Lisp has reader-macros (whereas you can't ignore Nim's syntax with macros, as flexible as it is). For example, Nim's async support (comparable to Python and C#) is a user-level library. So is, for example, pattern matching. Can Kotlin do that?
* Size: Nim compilation through C produces standalone and (relatively) tiny executables; it matters for embedded platforms. How does Kotlin fair in this respect?
[0] Lisp, scheme and other Lisp derived languages, of course.
Some people prefer Nim because of small things like syntax. However Go is much more popular. I will do more research on this subject and see if I can list the differences in detail. However any such list could be soon made redundant when Go 2 comes out.
Most of your list would probably remain intact. The main issue is that Go has a traditional garbage collector, and Nim has ARC, ORC, nogc, gogc, deferred reference counting, and more options for memory management.
I'm using the literal definition, "an important topic or problem for debate or discussion." By the main issue I mean the main matter of discussion/point of interest/topic to cover. Not suggesting there is something wrong with Nim's having various means of memory management. Default currently is refc (deferred reference counting) and it's reasonable. Arc is better for some use cases but not as ironed out as refc.
Nim has been trimming stuff out of its stdlib instead of adding them lately. And because of its huge focus on meta-programming almost anything can fit in an external package anyways (even async is a module in Nim, without any specific support in the compiler). The Nim language as such seems to be "complete" as it is now, and I'd say it's quite unlikely to gain bloat in any way that would affect people not using the bloated parts (i.e. the compiler will still stay fast).
> Memory leaks are not a concern as Nim uses one of several available garbage collectors. The new ARC option works with reference counting instead of a GC.
Using "no memory leaks" and "reference counting" in the same sentence is #fakenews. Reference counting leaks cycles unless accompanied with a tracing GC (at which point reference counting makes little sense).
> Reference counting leaks cycles unless accompanied with a tracing GC (at which point reference counting makes little sense).
Python proves otherwise. Reference counting gives you deterministic memory use and finalization except when a cycle is involved. The tracing GC helps for those cases (and libraries) that do introduce cycles.
If each one of your objects is in a cycle, then -- yes, reference counting makes no sense. If only 1% of your objects are in a cycle, it makes 99% sense.
Python is a trivial special case as it has no concurrency. In a single-threaded language, that indeed makes sense. Multi-threaded RC is extremely tricky to implement efficiently, so unless you can prove there's no cycles (or you don't care it it leaks memory), it makes little sense.
Oh, so now it's about "efficiently". Goal posts have moved.
No, it's not hard at all to implement efficiently as long as objects don't cross a thread boundary (and e.g. Nim's older GC used to enforce that condition, an old version of K tracked it and switched to "lock; xadd" to count references when something did cross a thread boundary IIRC, which made it inefficient only for those objects that crossed the boundary which usually weren't many.
It's way simpler than multithreaded mark&sweep, for example. Regardless - it makes a lot of sense. It might not make a lot of sense to you, but it does in general in most contexts.
These pros and cons appear to have been curated from around the web; this is a secondary source. If the final selection has passed throught the filters of passion and bitter experience, the author doesn't say. The parent site aims to fill itself with "Useful Tech Content", and this article reads like an assignment completed by a strong student.
So anyone can dress like Moses, come down off the mountain with tablets, and we'll debate the scriptures without considering the provenance? Good to know. California ballot initiatives often work that way.
It's a mix of research from the web (and I don't mean copy & paste), questions I and others have asked, and my own experience with Nim. This is not simply copy/paste. The rest of the comment I won't even bother to address as you sound like a troll.
- It has a bus/lottery factor of 1. The vast majority of all the changes were done by Araq and I have very little faith that the language would survive without him. This is even more pronounced with Zig (mentioned in comments here).
- It has had some very embarrassing bugs after the 1.0 milestone. Most of them were specific to Windows (e.g. [0]), which casts a lot of doubt on its cross-platform promise. Multiple times in the last year, when debugging a nim program, it turned out that the problem was in the language/standard library.
Now, these might not be reasons enough to not use nim, since it's a lovely language when it works, but a pro/con list should be honest.
[0]: https://github.com/nim-lang/Nim/issues/12315