Does that work in practice? I can't really imagine a single language that would be a good choice for "everything".
Does that work in practice? I can't really imagine a single language that would be a good choice for "everything".
* Shell scripting, I still assume most people will just use Bash tho: https://github.com/Vindaar/shell
* Frontend: https://github.com/karaxnim/karax or you could bind to an existing JS library.
* Backend: For something Flask-like: https://github.com/dom96/jester or something with more defaults https://github.com/planety/prologue
* Scientific computing: the wonderful SciNim https://github.com/SciNim
* Blockchain: Status has some of the biggest Nim codebases currently in production https://github.com/status-im?q=&type=&language=nim&sort=
* Gamedev: Also used in production: https://github.com/pragmagic/godot-nim and due to easy C and C++ interop, you get access to a lot of gamedev libraries!
* Embedded: this is a domain I know very little about but for example https://github.com/elcritch/nesper or https://github.com/PMunch/badger for fun Nim+embedded stuff!
Most of the disadvantages come from tooling and lack of $$$ support.
Well, interpretation is pretty useful for a REPL. And a REPL is not just useful to avoid compilation, but also as a way to explore a new API. And, most importantly, to preserve the results of long computations when you do not know yet what to do with it. If computing a value takes half an hour, you certainly don't want to recompute it each time you change something. Rather, you keep an open session, such as a REPL or a notebook, and keep computing with the already existing value
FWIW, this comparison between R, Pandas and Nim dataframes is quite encouraging: https://gist.github.com/Vindaar/6908c038707c7d8293049edb3d20...
This is one of the aspects that self professed R/Python datascience contenders often get wrong. The very bare minimum is a well supported and thought out dataframe library. Without that, the language is basically dead in the water. Nim seems to have a very well thought out API that also avoids many of the annoying aspects of Pandas (e.g. the huge waste coming from eagerly computing each vectorized operation into separate arrays).
Based on that and using a book theme, scinim getting started documentation is being built, e.g.: https://scinim.github.io/getting-started/basics/data_wrangli...
There is: https://github.com/inim-repl/INim and the builtin `nim secret`.
There is also a Jupyter kernel: https://github.com/stisa/jupyternim
Most of my work is time series analysis and I refuse to use an environment where samples are not explicitly labelled/timestamped and where the tooling does not support seamless operations that take this labeling into account.
So for my use case, a fully featured dataframe library is indeed a must.
True... May I introduce you to the filesystem?
but the architecture that imposed meat we were surprisingly resilient to power outages.
Any large nim projects that anyone can point me to would be helpful too, I’ll give the compiler a shot later today!
> Fast compile times: a full compiler rebuild takes ~12s (Rust: 15min, gcc: 30min+, clang: 1hr+, Go: 90s) [2].
The compiler is really big and self-hosted too.
For large nim projects check out: https://github.com/mratsim/Arraymancer or https://github.com/treeform/pixie (personal faves).
This is mostly an argument about "technically you can write anything with anything", except in nim's case it is also backed by extremely high flexibility.
EDIT: by flexibility I mean
- different backends they covet very huge ecosystems (Js and C, and by extension anything they you can interface with using C (like python))
- already mentioned metaprogramming
- support for low-level convenience features like custom operators
- different memory management options. If you want you can turn off automatic mm completely and write code that deals with pointers and stuff like that directly
- more niche things like support for embedding nim interpreter in your programs https://peterme.net/using-nimscript-as-a-configuration-langu...
Full stack Javascript enthusiasts are nowhere to be seen in this thread, but are writing their backend, frontend, desktop and mobile JS, WASM, Ethereum backend and the next ARM instruction set to speed up JS code natively, silently working towards total world domination. The nanomachines that will bring forth the end of the world will be running Node.js.
But I agree with you.
I'm curious how Nim fares for DS/ML.
One of the advantages of the language for DS/ML is the native "C like" performance with very low developer friction.
Another advantage from a library perspective is being able to automate fast, low level boiler plate code from easy to use DSLs using AST macros. For example a DSL could generate bespoke code for different data layouts and pipelines etc., giving you the best possible performance without the user worrying about it.
The latest incarnation of JS tools seem to be written in Go and Rust (esbuild and another one), not JS.
GC is an issue for compilers, or even just front ends, which create huge, fine-grained, linked data structures
You wouldn't be crazy for choosing JS for a new compiler project, even for work that had nothing to do with JavaScript.
(You would be pretty crazy to choose js to build a rich data science backend, in comparison).
I do agree the GC rules out some use-cases like many gaming applications.
You can, but that's a prerogative of all Turing-complete languages.
There are much better languages fit for the purpose, which is the point of this comment thread.
Keep in mind "a compiler" may not be for "a widely used general purpose programming language" but something smaller with a specific use, especially in the context of a company.
JS has many quality libraries for parsing grammars etc, and is Fast Enough for the purpose unless you need incredible perf - Python or Ruby, for example, might be much worse choices.
Even C++ might be a worse choice depending on your project's objectives (sure it might be faster but it might be a lot less maintainable, especially compared to TS). I also don't buy the argument that TS would make it harder to write a correct/safe compiler than C++.
Rust and Haskell may be sexy for the purpose but would be much slower to get started with, especially if your team isn't already staffed with experts. The Sorbet team at Stripe chose C++ over Rust because they felt developing with the latter would be too slow.
Keep in mind that most people are sticking with pure-JS build stacks even as esbuild et al are coming on to the scene. And the TS team has stuck with a Node compiler despite having the resources and know-how to use something totally different.
Please don't tell people to avoid writing a compiler in JS/TS unless you really know the specifics. :)
Of course, all of this does make me curious how Nim is for compilers (I imagine it'd be very, very nice).
There's also the fact that not all language are perfect. If they all are, the general language would always lose to the specific in every niche, so you need to do different things for the general to be worth. But languages aren't perfect, and you could prefer the general language even in niches.
There are of course a lot of other languages that influenced the syntax and semantics (like Ada, python, C++ and so on), and I omitted a huge number of extra considerations.
> [combining] Lisp's power with Python's readability and C's performance.
I'd say Nim still satisfies this very well.
1 - https://web.archive.org/web/20110704041631/http://force7.de/...
> We want a language that's open source, with a liberal license. We want the speed of C with the dynamism of Ruby. We want a language that's homoiconic, with true macros like Lisp, but with obvious, familiar mathematical notation like Matlab. We want something as usable for general programming as Python, as easy for statistics as R, as natural for string processing as Perl, as powerful for linear algebra as Matlab, as good at gluing programs together as the shell. Something that is dirt simple to learn, yet keeps the most serious hackers happy. We want it interactive and we want it compiled.
Nim seems to be what python should have been from the beginning. It is a breath of fresh air.
Or you can do high level stuff thanks to well though generics and meta programming.
The js backend is not mature enough to cover high performance web apps. It is more like a gimmick currently. Maybe a wasm layer could be as successful as rust's...
Metaprogramming is also surprisingly useful for low-level, embedded programming. Eg, using compile-time logic (branching, looping) to decide which bit in which register you want to twiddle, instead of doing it at runtime, which saves computation and (sometimes) code size.
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.
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.
You even have smart pointers if you need: https://nim-lang.github.io/fusion/src/fusion/smartptrs.html
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
> 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 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 ).
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 ).
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
Given all that, what are you still looking for to make the statement non-empty?
Along with general language characteristics such as being high level and productive like Python, but with intricate "bare metal" control when you want it, really does make it suitable for writing almost everything.