3 ms·
The probable gaps I see are embedded and certain branches of gamedev, and shell scripting. Regardless of what Nim says in its sales pitch, it is a garbage colle
by mumblemumble 5y ago
The probable gaps I see are embedded and certain branches of gamedev, and shell scripting. Regardless of what Nim says in its sales pitch, it is a garbage collected language, and garbage collection is not really optional. The closest options are nothing, automatic reference counting (ARC), and automatic reference counting with cycle deletion (Nim calls this one ORC).
Nothing at all might be fine for cloud lambda functions and command line utilities, but it generally isn't acceptable for long-running processes such as video games and firmware. ARC will still leak memory when there are cycles, so it can work if you are very careful about how you manage data. But it's trickier than what you get out of modern C++, and more resource-hungry than full manual memory management, so I can't really see this option being ideal for gamedev or embedded. And ORC is basically just Python's garbage collection algorithm, with all its strengths and weaknesses.
For shell scripting, at the end of the day, it is still a statically typed, compiled language. This just doesn't hit the sweet spot for a scripting language. In that context, the performance of the language itself doesn't really matter, the entire operating context is irredeemably weakly typed, and nothing you do will ever grow large enough for static types to help much with maintainability. I'd much rather have the fast edit-test cycles of an interpreted dynamic language.
That said, what I have successfully used Nim for is writing command-line tools that I interact with from shell scripts. But there, it's not replacing sh or perl or python, it's replacing C.
- PMunch 5y agoNim works super well for embedded. The thing is that you can turn off the garbage collector and do manual memory allocation if you want to. Or simply use ARC which works a treat on embedded. I wrote my own keyboard firmware in Nim (and did a presentation of it during NimConf 2021: https://www.youtube.com/watch?v=dcHEhO4J29U https://www.youtube.com/watch?v=dcHEhO4J29U). It runs super fast and the code size is smaller than some simple "Hello world" level programs using the Arduino system. As for gamedev the ability to tune the GC by turning off automatic collection and then running it with a time-limit is perfect for preventing lag-spikes when a lot of stuff is going on (looking at you Java..). Nim actually performs very well, and the garbage collector does a great job of just getting out of the way and letting your programs fly. Your point about shell-scripting is kind of valid, it is indeed a weakly typed world. But with how fast Nim compiles the edit-test cycle feels as fast as Python, and you save a lot of time from having a silly typo that you only encounter after having run your script for a little while. The reason why Nim is good for pretty much anything is that the speed of the compiler and the garbage collection will rarely if ever stand in your way, and the flexibility of the syntax that stems from meta-programming allows it to be molded perfectly to the use-case.
- elcritch 5y agoNim does work very well for embedded. From small stack only memory management, possible with value types and basic Nim proc's. Or use ARC for MCUs with 100's kB of RAM, which are fairly common nowadays.
- DeathArrow 5y agoBut garbage collection is really optional. You can use manual memory management: https://play.nim-lang.org/#ix=3uVt https://play.nim-lang.org/#ix=3uVt You even have smart pointers if you need: https://nim-lang.github.io/fusion/src/fusion/smartptrs.html https://nim-lang.github.io/fusion/src/fusion/smartptrs.html
- arc776 5y ago> it is a garbage collected language GC has to be explicitly attached to types. By default everything is a value type allocated on the stack, and managed by scope. Nim is also clever enough to optimise away copies for value types (such as passing immutable parameters). GC is only really used for reference semantics. > garbage collection is not really optional Sure it is. Some of the stdlib uses GC for dynamic lists, but if you're after ultimate control you can easily make your own dynamic lists using manual memory management thanks to the type system and move semantics. > ARC will still leak memory when there are cycles, so it can work if you are very careful about how you manage data. If you have cycles and want GC, as you mention, you'd use ORC. As a point of comparison, Rust references also leak with cycles https://doc.rust-lang.org/book/ch15-06-reference-cycles.html https://doc.rust-lang.org/book/ch15-06-reference-cycles.html > But it's trickier than what you get out of modern C++, and more resource-hungry than full manual memory management, so I can't really see this option being ideal for gamedev or embedded. I'm curious how ARC/ORC are tricky to use? Currently it's just a compile switch (soon to become default). There's not really any 'usage' at all, it just switches assignment to move semantics where possible. > I can't really see this option being ideal for gamedev or embedded. My personal experience is that ARC/ORC are extremely performant. They don't "stop the world" like Java/Python and are designed to be suitable for embedded work. In particular ARC offers "deterministic performance for hard realtime systems". For ORC and other GCs you can manually step collection and define soft-realtime collection pause limits. You can even plug in other GC implementations, or create your own if you have specific requirements. The memory model https://nim-lang.org/docs/gc.html https://nim-lang.org/docs/gc.html states: Nim provides multiple paradigms for needs ranging from large multi-threaded applications, to games, hard realtime systems and small microcontrollers. As an example of a large and complex project running on embedded and using GC, see the Nimbus Ethereum client. Embedded is actually a big use case for Nim specifically because of how memory and CPU efficient the language can be, and how tunable everything is. Besides, generating a lot of garbage each frame is a design issue in gamedev. Normally you'd preallocate or at least chunk allocate. > ORC is basically just Python's garbage collection algorithm ARC is more similar to Rust's move semantics or C++'s smart pointers, and ORC just adds a cycle collector on top. You can also mark types as `acyclic` to remove cycle collection by type. What makes it ideal for gamedev is high productivity, run time execution speed, interfacing with C/C++ natively, and tools like AST macros. > For shell scripting, at the end of the day, it is still a statically typed, compiled language. This just doesn't hit the sweet spot for a scripting language ... the entire operating context is irredeemably weakly typed, and nothing you do will ever grow large enough for static types to help much with maintainability. I think scripting being "irredeemably weakly typed" is a matter of opinion. With good type inference, you get almost all of the advantages of dynamic types, such as fast edit-test cycles, without the pain of not knowing what anything is. Weak typing is ultimately just how you define converters, and I prefer making that explicit rather than lenient (libraries can make typing effectively 'weaker', e.g., https://nim-lang.org/docs/lenientops.html https://nim-lang.org/docs/lenientops.html ). There's nothing you can't do in statically typed languages that you can in dynamically typed languages. The only disadvantage Nim has over, say, Python, is it's weaker REPL support for now (hot code reloading is WIP: https://nim-lang.org/docs/hcr.html https://nim-lang.org/docs/hcr.html ). The nimscript subset of the language available at compile time is actually really good for scripting on its own, and is used for scripting builds without needing a separate language: https://nim-lang.org/docs/nims.html https://nim-lang.org/docs/nims.html