Also, the organization has no desire to invest in training or experimenting. The project is funded by the "business" and they want to see a business result in return for their money ... so you basically you sneak in a bit of time as you try/test something new. Nim won out by somehow getting a team with python expertise learn and deploy their product fast enough.
You could also describe it as being competitive with Rust, but with more compromises for the sake of developer ergonomics. Garbage collection, for example.
For my part, I'm finding it attractive as a potential Java-killer. It isn't write-once-run-everywhere, but, now that x86 and Linux have eaten the world, that's not quite such a compelling feature anymore. And Nim smooths things over a bit by making cross compiling dead easy. In return, I get better type safety, better performance, a much better C FFI, and less verbose, easier-to-understand code.
I think there's not much merit in discussing "C-flavored Python" as a description of nim, as that description seems just wrong.
Aside from significant whitespace, I don't find that many similarities with Python syntax.
Describing Nim as non-functional is misleading. Nim does have functional constructs and is a mixed-paradigm language involving both procedural and functional elements, just like Python.
"Firmly statically typed" is misleading. It's actually strongly-typed with great capabilities around type-inference so that, at times, you start to forget that it's typed in the first place and gives you a similar feel to a dynamically-typed language like Python.
Nim can run with garbage collection disabled. As a matter of fact, I seem to recall that the authors postulated that as a basic requirement that the language should be able to run in a low-level systems programming mode with garbage collection disabled (where it would be able to compete with Rust), and in a more high-level mode where it would rather compete on developer ergonomics/productivity.
I find Java-killer a potentially misleading analogy. I do think that it captures the kind of platform-independence that matters nowadays. And that is no longer Intel vs Sparc and Windows versus Linux, but rather the native ecosystem versus the JavaScript ecosystem.
Nims GC is able to either be controlled in terms of when and how long it runs, and it can be completely disabled in favour of manual memory management. In fact people have gotten it to run on really low-powered microcontrollers like the Attiny85, as well of course as various Arduino boards. The benefit of Nim in these systems is that since it compiles and has such a rich macro system your are able to write abstractions that the compiler will turn into highly efficient code. So you can still write business logic level readable and maintainable code, while the compiler spits out super-optimised versions. This of course requires you to first write these macros, but often times a little goes a long way.
Well: Nim is similar to Python in many respects, it's just not "C-flavored Python".
It has significant whitespace like Python. But since it has a lot of language constructs that are different from Python, it's a bit tedious to try to otherwise compare the syntax a great deal, and it has many elements to its syntax that are quite unique.
Saying that Nim is statically typed whereas Python is dynamically typed is exactly a feature that's a slightly unfortunate pick for trying to contrast the two, because type inference is trying to bridge the gap and give you something that's a bit in-between in terms of how it feels to the programmer.
Nim is similar to Python in that (a) It's very cleaned-up and allows you to do a lot of stuff and complex stuff with little code, without sacrificing clarity and readability. (b) It puts the programmer in a cognitive mode where he can think first and foremost about the problem at hand and not have to concentrate on the programming language so much. (c) It gently guides the programmer towards good programming practice without being patronizing. (d) It has a fast learning curve,...
Essentially all the things that make Python great are found here as well. But nim gets there on its own, not by replicating elements found in Python a lot. It's very unique in a way that makes nim a great choice of language in situations where Python isn't (like systems programming or writing code for the Browser ecosystem).
</subjective>
It seems like you're hyper-focused on a rather skewed interpretation of my first sentence, to the point that you largely ignore the second sentence. Or at least you seem to ignore everything after the word "but", which, given what the word "but" is often used for, is a rhetorical move that has a way of enabling interpretations that tend to be close to the opposite of whatever was originally intended.
Parent poster has it right. I picked that initial comparison to Python by way of introducing one of the more popular summarizations of Nim, so that I could say why I don't think it's a good summary. If I didn't put it emphatically enough to satisfy you, I apologize. I apparently don't have anywhere near as strong of feelings on the subject; Nim's just a language I like to program in sometimes.
Probably because most people are more familiar with Python than Ada and Modula (combined) ;)
I guess it depends on your previous experience. Some people will only see Python, others might think of Nim and its syntax as "Pascal for 21st century" (fun fact: the original Nim compiler was written in Pascal).
But, being a JVM language, it's still stuck with all of the Java shortcomings that I had listed before: Achieving a decent level of type safety is impossible, the FFI is still a pain to use, and you've got to go through contortions to get really good numeric performance. Because all of those problems are characteristics of the JVM's run-time environment, not the language you're using to target it.
The only KVM in town is Android.
I used it where I would use python - backend of web apps. But now instead running a cluster of servers I can just run 1 because nim is fast.
I also used to write frontend in CoffeeScript, but switched to nim because I can share code between backend and frontend. I don't have typos. I don't inherit any JS or OOP legacy like TypeScript.
This was sort of my use-case and experience as well. I also find it can do what I needed JavaScript-based CLI tools to do with less dependencies/ecosystem bloat, and the resulting code is a lot nicer to work with. People have told me that's because I was using JS wrong, but I felt like Nim was such a huge step up for my use cases.
It's also just a pleasure to learn something new occasionally.
For a side project of mine, I recently re-wrote the same code in a dozen or so languages. The application reads input data from text file and does a bunch of conversions to integers and floats (atoi and atof). It then runs through an algorithm that does calculations and identifies proper actions. Finally, it writes the output data as formatted text file. Regardless of implementation, it runs quick. Sorry I can't provide more details on nature of the code (it has IP that belongs to another person).
Here are the top 10 best execution times (all run on same hardware). Times obtained by 'time' utility (e.g., "time ./run.sh"). Some of these were run on Ubuntu 16.04 and a few were run on FreeBSD 11.2. Where the compiler has optimization flags, I used it.
1. C++ 0.04 (gcc version 5.4.0) 2. Rust 0.11 (version 1.37.0) 3. Go 0.13 (version 1.12.7) 4. D 0.16 (tied with Pascal) (DMD64 D Compiler v2.073.2-devel) 5. Pascal 0.16 (tied with D) (fpc 3.0.2) 6. C# 0.25 (mono 4.8.1) 7. Nim 0.50 (1.0.0) 8. Kotlin 0.81 (Kotlin version 1.3.50-release-112, JRE 1.8.0_222) 9. Java 0.95 (openjdk version "1.8.0_131") 10. Scala 1.79 (version 2.12.2, running on 1.8 openjdk)
1. C++ 0.04 (gcc version 5.4.0)
2. Rust 0.11 (version 1.37.0)
3. Go 0.13 (version 1.12.7)
4. D 0.16 (tied with Pascal) (DMD64 D Compiler v2.073.2-devel)
5. Pascal 0.16 (tied with D) (fpc 3.0.2)
6. C# 0.25 (mono 4.8.1)
7. Nim 0.50 (1.0.0)
8. Kotlin 0.81 (Kotlin version 1.3.50-release-112, JRE 1.8.0_222)
9. Java 0.95 (openjdk version "1.8.0_131")
10. Scala 1.79 (version 2.12.2, running on 1.8 openjdk)- "Transpiled" to C, with some options regarding runtime library, which means you can target any uController out there
- Good metaprogramming support
- Static and _strong_ typing
- Consequently, precise type aware function dispatch
- Type inference
- Good generics
Also, more stuff like covariants and contravariants and... maybe you just have a look-see? ;-)
Edit: Yes, those are very valid and reasonable questions. Clarifying that it's not meant as trolling is also valid and reasonable, because writing is easily misunderstood in exactly that way - which is the reason smileys were invented. (And, to be clear, I'm not accusing anyone of missing smileys or of trolling. I am trying to express my agreement with both parent and grandparent.)
(I'm not accusing the granparent post)
So, in order to avoid bias on the reader part, I preferred to explicitly tell it was not trolling.
The cons are its lack of enterprise backing, its smaller community and its syntax, if you don't like either Pascal or Python.
You can also entirely disable the GC or replace implementation.
Nim can run without OS and on microcontrollers.
I mean, it actually is C, since the code is transpiled to C.
Or consider: Every native-compiled language ends up as machine code, which is equivalent to assembly language, but for most (perhaps all) it would be grossly misleading to say "as fast as assembler".
Your comparison to machine code (or human readable assembly code) is less useful in that such a statement means very little until one knows how said machine code is being produced (e.g., manually, from a IR, etc.).
That a language is compiled to C does not mean that its compiler is going to be able to produce a C program that's as good as a that well-written C equivalent. (A relatively obvious example would be a compiler that introduces a heavy runtime, and doesn't give the C compiler enough information for it to get rid of the runtime)
It's the same with assembly code: that a compiler produces assembly does not mean the resulting program is fast.
That’s your interpretation, which is fine, but the objective meaning stands. Even the idea of “well-written C” is, in my experience, fairly subjective amongst C programmers.
Where do you see me claiming otherwise?
> At the simplest level, the compiled code could add a bunch of unnecessary function calls and pointers and other forms of indirection that wouldn't be present in hand-written C.
Again, why are you telling me this? Please quote where I claimed otherwise.
> But for a more extreme example, you could also compile an interpreter or VM to C, and it would still be much slower than the equivalent hand-written C code.
The more that I read your response, the more that it seems that you’re debating yourself, because I’m not sure why you’re telling me this. You started your response by telling me that I’m “missing the point” when, in reality, you seem to have not even read my point. My main point was the following:
> If the code from which the resulting machine code is compiled is C, then it’s objectively “as fast as C” […] your resulting program will perform as fast as a C compiler [worth its salt] can get you.
This is true. I made no claims re efficiency; “as fast as C” and “as fast as efficient hand-written C” aren’t interchangeable claims. Forgive me for not assuming efficiency, because I’ve seen a good amount of inefficient hand-written C code in my years.
> This is why "as fast as C" typically refers to normal, hand-written C code—even though there is no formal definition for what "normal C" looks like, it's still a useful description.
Says who though? I’m professionally experienced in C, and as is very clear by this discussion, it’s down to individual interpretations.
That some particular C program exists that is at least as slow as a program in some other language is always true, trivially, and so is not a good interpretation of "as fast as C" regardless of its objectivity.
Being as fast as C is not about using C as an intermediate language but having data structures and control flow that resemble what C compiler have been optimized for.
Case in point, Haskell GHC is capable of outputting C code but the algorithm will not get C performance (or Haskell performance without this intermediate C representation).
But that doesn't at all follow from compiling to C. I gave one example above; here's another. Perhaps my programming language has arbitrary-length integers and the C code it produces for a simple loop looks something like this:
bignum_t i = bignum_from_int(0);
bignum_t x = bignum_from_int(0);
while (i < bignum_from_int(1000000)) {
bignum_add_in_place(x, bignum_bitand(i, bignum_from_int(1)));
}
Corresponding code in "normal" C would use machine integers and the compiler might well be able to understand the loop well enough to eliminate it altogether. Code like the above would run much, much slower, despite being technically in C.(A neat tool in one's toolbox, of course. But just transpiling to C does not get one as fast as C.)
I've been trying to find out if I can take the generated C code that nim produces and, for example, compile it on some exotic architecture (say an ancient solaris/sparc system or some aix/power thing, or some mips microcontroller with linux) however I can't find any examples of people doing this...
Is it possible? Or should I abandon hope and continue writing C for these platforms? :}
Give it a try :)
[0]https://stackoverflow.com/questions/29956898/how-do-i-get-th...
And for CPUs - https://github.com/nim-lang/csources/blob/master/build.sh#L1...
Nim had the following appeal for us:
- Ethereum research is done in Python, we actually started our code with a tool called py2nim to convert a 50k lines Python codebase to Nim in less than a month (and remove cruft for 3 months but that's another story).
- Nim allows us to use a single language for research and production: the Python syntax, and the fast compilation speed are very helpful. In particular researchers found the Nim codebase easy to debug as the overhead vs the Python spec was quite low (and the Python spec is using types with mypy)
- Nim has a easy C FFI and is one of the rare languages that can directly use C++ libraries, including header-only template heavy libraries.
- Nim allows tight control over memory allocation, stack vs heap objects, has support for Android and iOS and very low-memory devices as well.
- Nim also can be very high-level
- Nim is as fast as C and can resort to inline C, inline C++ or inline assembly when needed. (inline javascript or Objective C are possible as well)
- You can produce WASM code via clang, emscripten, binaryen, there is even a Nes emulator demo from 2015 running in Nim compiled to WASM here: https://hookrace.net/nimes/
- Nim has a strong type-system, including generics and type-level integers, boolean and enums.
- Nim has probably the best compile-time capabilities of all languages. I'm writing a deep-learning compiler in Nim macros. Someone wrote a Cuda code generator in Nim macros, and the code generation is extremely nice to write a VM, an emulator or any kind of assemblers as you don't need to use an intermediate step to generate your opcode tables or generate your functions from that table.
Now on a personal note, I use Nim to write a deep learning framework similar to PyTorch or Tensorflow.
I think it's the best language to solve the 2-language problem, i.e. write research in Python, R or Matlab and production in C, C++ or Fortran.
The operator overloading or even operator creation is very useful. The macros allow me to have a slicing syntax similar to Numpy, something impossible in C++. Compilation speed is very nice as a developer, I don't know how people deal with waiting for C++ CI.
I reimplemented a matrix multiplication with performance similar to handwritten assembly BLAS from OpenBLAS and MKL in pure Nim so I'm not worried about performance as well.
Now I'm onto refactoring the backend with a proper compiler (similar to Halide but since it will be macro-based, there won't be the 2-stage compilation issue)
vec[3_s & 4]
is very much possible in C++. It's only two characters longer.(C++ doesn't have a ':' operator, you'll need to use some other symbol.)
For me, Julia completely addresses the 2 language problem. In practice I think it now simply needs a stronger ecosystem, better static analysis, and bug fixes, but I am very happy with the language design.
Their goal is to get Eth2.0 (and 1.0) running on very low resource environments such as raspberry pi and turnstiles.
What this should tell you is that:
* Nim is close to the metal enough to run with high performance and low resources.
* In a cutting edge research arena, where the math is still being decided, Nim allows such rapid prototyping that the team is on par with much larger teams in much more established languages.
* All the tools required to build an ethereum platform are present and running, such as security, encryption, and networking such as devp2p. Here's their eth library docs for some of the contributions: https://nimbus-libs.status.im/lib/nim-eth/
Status is pretty dedicated to open source, and whilst they're the biggest patreon donor, the Nim team is completely autonomous.
https://github.com/danielecook/seq-collection
And the second:
https://github.com/danielecook/tut
The second one has a really useful utility called "stack" that you can use to concatenate datasets where one might lack some columns or the columns come in a different order. It glues it all together and has an option to include the filename. It's useful for data analysis.
Both of these lack 'polish' at this point but a few of the subcommands work quite well.