I stopped trying Nim in 2017 when I found out that the only worth feature were the macros. Red flags I saw:
* A return variable within procedures that works in the same fashion as an assembly routine with a registry
* Mutable strings
* Mutable everything
* Hate speech against functional concepts in the community (with all the related biases that this brings)
* Some arrogant community members were tolerated just because they wrote popular blog posts on Nim implementing a fashionable pet project.
* no clear consistent design direction
* too many pragmas
* too many pascal syntax mixed with other language syntaxes
* no module namespacing
* modules worked not much better than C libraries... (I am generalizing)
* poor ecosystem made out of incomplete mutable libraries
* python 3 (without any library or optimization) was faster than compiled nim to count words on a moderately large text.
After I realized about python was easily beating Nim in spead and readability only with the standard library without any optimisation on python's side (and Nim being fully compiled), my interest on Nim went down to 0. I thought there were other places were I thought I could better invest my time.
Did something from that list changed? is there any reason to look at Nim again in 2019? did someone here had a better or different experience than mine?
EDIT: format, reworded sentences, expanded opinions
Nice list, thank you for compiling it. I'm one of the Nim core devs so I naturally disagree. A lot on the list is painted as a negative, whereas I see it as a positive, in particular:
> * A return variable within procedures that works in the same fashion as an assembly routine with a registry
Not sure I see the parallels between assembly and I don't understand why you think this feature is negative, can you elaborate?
> * Mutable strings
I love these! No need for messing around with `StringBuilder` and the like.
> * Mutable everything
That's simply false. You can choose between mutability and immutability, in fact you can even have an immutable `string` if you really want one: `let x = "asd"`.
Now let me discuss some of your other points:
> * Hate speech against functional concepts in the community (with all the related biases that this brings)
Communities are large. A lot of us love functional programming and are bringing more and more of it into Nim.
> * Some arrogant community members were tolerated just because they wrote popular blog posts on Nim implementing a fashionable pet project.
Can you elaborate on who this was and how/where they were tolerated?
> * no clear consistent design direction
> * too many pragmas
> * too many pascal syntax mixed with other language syntaxes
These are mostly subjective so there isn't much I can say. Perhaps Nim just isn't for you due to its syntax, but many out there love it.
> * no module namespacing
> * modules worked not much better than C libraries... (I am generalizing)
This is false too. Every imported module is in its own namespace.
> * python 3 (without any library or optimization) was faster than compiled nim to count words on a moderately large text.
Hi Dom96, thanks for answering point by point. Unfortunately I cannot answer all of these things since I got this impression about two years ago, and things might have changed or perhaps I got them wrong (as you say some of them are subjective).
For example, I cannot tell what compilation option I used but I remember I went for the max speed I could and that I used default Nim language constructs and default python constructs (no libs), the compilation was one of the most sold features so I believe I used the release mode and that there was a marginal difference in favouring of python (subsecond). Think However that python has also many optimizations for string manipulation and that under the cover all runtime objects are references whereas in compiled languages developers are naked in front of the CPU.
Knowing that you are core-dev I must say that building a language is very hard, and that by not bringing much to the state of the art and overselling too early it is easy to get compared and valued by subjective aspects or mere impressions. Heads up, keep it with the great work and do not take it personally, make the language shine in some unique aspect.
Also do not forget that my comment was just an unfavourable opinion based on some observations I made years ago; I could change my opinion on the language anytime and give it again a chance if it brings me any benefit for my development, or it is fun, or it has some solutions for the problems I need to solve.
I've just been learning Nim lately, and, for the most part I like a lot of how Nim handles these things. Getting to choose between mutability and immutability, together with procs having to explictly say when they intend to mutate one of their arguments, is fantastic.
That said, I do agree with GP's first point, and can at least elaborate on it from my own perspective: At first I liked the implicit `result` variable, mostly just because it saved some typing. I quickly found it to be a source of confusing bugs, though, because accidental mismanagement of the feature would result in default values being implicitly returned rather than compiler errors. I think I ultimately agree with the Zen of Python here: Explicit is better than implicit.
Also, Nim has, by my count, three different ways of returning a value from a proc: The implicit `result` var, returning the value of the last expression, and explicit `return` statements. It has four if you count modifying ref arguments. That's pretty TMTOWTDI for my tastes.
I think what op meant about importing is one of the things I don't like about Nim. If you have
import os
then both
existsFile("test.txt")
and
os.existsFile("test.txt")
will work whereas I prefer Python's forcing you to use the later. Nim is definitely a language for small teams where you can expect everybody to agree on sensible best practices and not get too clever.
You can follow that convention and it works but you could also just have the convention of always using os.existsFile. Again, if you follow sensible rules when using Nim you're fine and the compiler will protect from mistakes better than most compiled languages. It's just laziness and cleverness that are dangers :)
In my experience code that needs to generate strings in Python would usually use a list of strings and then use `join` at the end. What's the problem with just making strings mutable?
>What's the problem with just making strings mutable?
They are not arrays of characters until you use ASCII/KOI8 or similar encodings. So there is no point in mutating them, you need unicode normalization facilities, formatters and stuff to deal with them properly. And a proper mutable unicode string would give you a terrible performance penalty.
It also applies to things such as using strings as dictionary keys. Immutable strings allows you to use them as keys without worrying about them being modified and breaking things. It's why Ruby encourages symbols as hash keys. I don't know Nim yet so I don't know what their solution is.
It's also what allows Python to do interning of strings, since they can't change.
Nim gives you the choice of whether something is immutable or not. A `Table[T, Y]` (Nim's dictionary type) simply doesn't allow the key to be modified, no matter what the key type is.
I think this is really what it comes down to in Nim. I personally prefer immutable strings, but I don't think it would be wise to force them to always be immutable in Nim, because then you'd have this weird language wart where
let foo = someValue
var bar = someOtherValue
yields an immutable foo and a mutable bar for all types except strings.
I'm guessing that's a detail that's lost on folks who haven't spent much time with Nim, because the way mutability and immutability work in Nim is different from how it works in any mainstream language.
I don't know a lot about Nim, but I do know D, and there `string` is just an alias to `immutable(char)[]`. String literals are of this type. But one can manipulate mutable arrays of char all day long if needed.
you are underestimating python; it has many ways of concatenating strings, such as operators, buffers, templates, streams, the join method etc also.
By having mutable strings you lose the chance of relying on them as hashable objects and constant cost for comparison and several memory optimizations for duplicates and other optimizations when you have a runtime. There is a lot to win in the big game (or perhaps not that much if someone is thinking too much into a constrained system).
mutable string: a buffer made of chars which can be modified on demand with little memory
immutable string: some abstract data which ensures some properties that can be leveraged for many purposes
The last language I would take as an example for string is python.
The disastrous handling of the transition python2 to python3 with UTF-8 string and the idiosyncratic nonsense like " ''.join([str1, str2]) to concat anything speaks for themselves.
In python you can concatenarme strings using the operator plus, using templates, the method join, putting them in buffers or streams and many other ways just using the main python builtin functions just to name a few (no std library yet!)... the support for slicing is also very good and compare strings has a cost O(1) due comparing IDs instead of their content every time (optimize thanks to immutably as property).
Python 2 had several shortcomings, but not with strings I think. The transition to python 3 is more more a matter about a migration execution rather than a technical aspect related to strings (which I don’t find that terrible, especially given all facilities provided to make the migration easier to the new incompatible runtime).
> The transition to python 3 is more more a matter about a migration execution rather than a technical aspect related to strings (which I don’t find that terrible, especially given all facilities provided to make the migration easier to the new incompatible runtime).
That's political talk. In practice I never have seen a python library that do not blow up when migrated in Python 3 with a Unicode related error, because one of the dev was using python2 string as binary vector.
Regarding just the last point, I also came across a case where Python (and Node) were outperforming my Nim code (just counting lines in a file). But I just happened to be using a slow line reading thing [1].
You should definitely give Nim another shot. It has been very pleasant to use.
> I love these! No need for messing around with `StringBuilder` and the like.
But if I get a string passed to me and want to hold on to it for later use, I can't be sure that someone else holding a reference to it won't modify it after I got it, right? So I will have to make a copy to be safe. Or does Nim solve this somehow?
Wow we have had some different experiences. Going down your list, the only thing that has been a problem for me is the ecosystem issues, and that comes with the territory with smaller languages. The most surprising was your issues with speed, which I feel like had to have been a compiler or standard library bug of some sort. I use Nim on a side project with moderate calculations, and it finishes in about the time it takes nodejs to do Hello World. I think most of your list comes down to preference though. Nim isn't a fully FP, immutable language. It supports FP more than Python though, and probably as much as JavaScript does.
> python 3 (without any library or optimization) was faster than compiled nim to count words on a moderately large text.
I'm not a fan of Nim because types go after the variable. But the fact that you did not consider that you may have messed something up and just thought "yeah totally, a language built to compete with C++ is slower than python", really discredits your entire post.
Have you considered that in instances where type inference (I haven’t used Nim, but this is true of Rust, Kotlin, Swift, etc) can be used, having the type follow the variable is vastly superior from a readability point of view?
It didn’t take me long to prefer this syntax to that of Java, C, C++, etc.
I do not understand how having it on the right should help where type inference is used, as in that case you do not write the type at all! There's absolutely no difference in readability.
How about we consider the normal case (where you write out the types):
int num_entries = ..
float div = ..
float result = num_entries // div
vs
num_entries: int = ..
div: float = ..
result: float = num_entries // div
Because they are on the right, they aren't aligned which makes it harder to parse (imo). It gets even worse with more complicated types (lists etc).
> having the type follow the variable is vastly superior from a readability point of view?
[citation needed]
The way Nim, Rust, etc do it, with a useless 'var' keyword even when a type is present, is clearly needlessly verbose (ie, inferior, though I'd hesitate to say vastly), but I'd be interested to see a analysis of the merits of something like "Foo[2] foo = bar()" vs "foo Foo[2] = bar()" (or maybe that should be "foo [2]Foo = bar()"?), since it hadn't actually occurred to me to use the latter order seperate from the useless keyword.
That’s quite a trivial reason to dislike a language! There are quite a few languages, including some very popular ones, like Kotlin, where the type comes after the variable.
your recollection of your experience with Nim performance is what it is, but it is at odds with just about every other account of Nim, including by people who really dislike it. Your “it was a long time ago, I don’t remember” doesn’t make it credible either.
Other comments are more a matter of opinion or view, but with respect to speed or memory use - Nim competes favorably with C++, D, Zig and friends. Neither CPython nor PyPy is in the same league.
So I wouldn't be at all surprised if you could make the same mistakes in Nim. But of course it would be unfair to claim that that means Nim is slow in general.
I have not programmed in Nim and I am a Pythonista.
Having said that, I had to parse the whole wikipedia dump xml file once and extract just the text. The python code for the same was so slow and would have taken days to go through the whole xml file.
In my quest to find something faster, I came across a nim program that would take the xml in and dump a plain text file (or markdown?) file. It did the work within 2 hours.
So I don't believe it was slower than python.
Nim certainly has it's place and it is more comparable to go in speed.
It was very straightforward code looping, counting and storing strings in memory and writing to a file. Looking in perspective my guess is that the optimized C runtime of python (IO and optimized string references) competed against Nim's bare strings.
If you are a pythonista I have a question for you, especially since I could still give Nim a try, how much effort would be for you to add 2 or 3 generators and asyncs in the python code and put in place a better architecture without any macros? how easy is the same thing in Nim without any library our of the standard library?
This speed of prototyping and bringing a better architecture to the solution sooner matters a lot more to me than raw speed (that comparison against python in speed was the last drop).
I believe you when you say that Nim won, after all they promose that some parsers such as csv parser could fit in the L2 cache and so on... hopefully the language and quality of libraries has improved.
P.S. how big was the whole wikipedia as XML? all languages?
Python is intentionally a kitchen-sink type language that provides everything in its standard library, whereas Nim is intentionally the opposite. More and more things are moved out of its standard library to the package repository (Nimble).
Thus, asking someone to write a stdlib-only solution in Nim is a bit of a trick question...
Honestly, I feel like you just want different things from your language, and you'd prefer something like Scala or Haskell.
I've never heard "hate speech" against functional concepts: I've worked on functional-ish/pattern matching libs and i know other people from the community that love functional lang ideas. However those ideas are not as prevalent as in functional languages tho(obviously).
I'd say a lot of those points are very subjective(syntax/pragmas/modules etc). It's true that the ecosystem is still small and documentations is not good enough sometimes: this is something that probably can't change without a stable 1.0 first(and serious doc efforts started last month).
I never used Scala, Haskell or a functional language other than a small pet project on clojure I usually write small functional snippets within OOP for python (so my job colleagues can still understand most of my code/structure).
"Hate speech against functional concepts" was a metaphor for repetitive comments without foundation against some concepts and highly respectable design choices, where I often saw people pretending these to be dumb without really discuss the points properly, or exploring choices or constructs without acknowledging any single good thing from it. You can consider that a subjective, generalized opinion if you want.
Think that "that functional approach" has a lot to borrow from, even when still working within a mostly imperative language. Perhaps it is not a true red flag but in my eyes it was an involution. Totally subjective if the focus of the language is becoming a better and more advanced C (rival of Golang for example)
No, it was a groundless inflammatory comment. It's not ok. It's not "a metaphor". It's needlessly offensive and very harmful to Nim and its community. Your comment is currently at the top of a thread, with a very heavy accusation towards the community - tolerating hate speech of any kind is basically as bad as it can be for a community. Even on HN, there will be many people who won't read your further comments, won't know that it's "just a metaphor", and will believe it. Then, when I try to invite them to some Nim conference, they'll tell me that "Oh, Nim... Would be good, but the community is so hostile, so I'll pass".
Please, at least realize what you have done, and don't do it again. Please.
@klibertp I disagree with you. Everyone here is a grown up and "hate speech" cannot be directed against an algorithmic abstraction or a way to organize code. Criticism is a valid form of opinion, including criticism on informal elites in online communities, especially within opinions which by definition are subjective.
If you feel my metaphor is hurting that's because you feel targeted there in some way, but here everyone is adult enough to build their own opinions and look by themselves there. If my comment made it to the top it is because it was upvoted in spite of having the way of use the language I have and the way my opinions are. That wasn’t the first comment when I wrote it.
I hope you realize what you are doing censoring people's opinions based on your subjective judgement of everyone else’s possible reactions, discarding people’s own judgement.
Saying that a community could die because of a negative opinion online is senseless, precisely because truly injust opinions positively reinforce groups by creating a feeling of resistance and victim identification. But my opinion was honest and metaphors are just a way of using language.
Anyway, I respect mostly all opinions but censorship. And in regard on whether somethign is hate speech or not... really, criticize an abstraction, not even an object, who could take that sentence in a literal way and interpret it by the word? You are drowning in a glass of water (yes, that's another metaphor, just in case).
The majority of your posts here got heavily downvoted if I go by their color. One got flagged (not by me or anything). There's probably some meaning in that.
You are going here totally ad-hominem here. Do you mean about the three posts where I speak about what a metaphor is? isn't the usage of the language a complete subjective opinion and cultural aspect? the main post is still upvoted (an opinion comment) and as I said earlier here no ones wants to score anything... except the several lobbies that want to promote their solutions in order to sell them to the Hacker News audience.
And about the votes; not sure how you deal with it, but I take it easy with the downvotes, I won't censore my opinions because of them; and at the end of the day not really much people cares about other's opinions let alone votes, karma or reputation in an anonymous forum. If someone was decided to use nim they will give it a try by themselves anyway.
Wait, how? I just stated the fact as I perceived it - most of your posts were in various shades of gray. That's it. I didn't say anything about you, personally, which is what 'ad-hominem' would be.
> lobbies that want to promote their solutions in order to sell them to the Hacker News audience.
I'm not involved in any way with any of such lobbies in general, nor with the Nim community in particular. What I'm interested in is the quality of the debate on HN.
> I won't censore my opinions because of them
I can't understand why do you insist that I wanted to censor your opinion. I object to one particularly stupid way of phrasing that opinion. Had you written something like "some members of the [Nim] community seemed to be dismissive or even hostile to the ideas of functional programming" - I wouldn't have said anything! It's the same opinion, and it would cost you nothing to think for a bit and consider your phrasing a bit more carefully. I would even give you a benefit of a doubt if you used quotes around "hate speech", giving a hint that it's a metaphor - but you didn't, you played it straight, and I don't understand why. Is inserting quotation marks that much of a hassle to you? Is it that you don't understand, or perceive, the difference between 'hate speech' and '"hate speech"'?
As for the "usage of language" being subjective - sure it is. While they are subjective, there are norms and rules to follow, depending on the time and place. Imagine yourself farting loudly on a family gathering, then insisting that you're entitled to do just that because it's the way you express yourself and not doing it would be censorship. Yeah, you would be right, actually, but do you honestly expect people around you to just accept the stench?
I would like to ask to simply refrain from such farting, metaphorically speaking. As I already said, accusing a community of tolerating hate speech of any kind is a very serious thing and shouldn't be done lightly. It's similar in weight to saying that someone is a Nazi, or racist, or misogynist, or a terrorist. Would you like to be called a terrorist, even if it was said metaphorically?
To summarize: I'm not talking about the content of your opinions - arguing with them is a separate matter - only about the way you phrased them. I don't want to censor your opinions. I do want to censor the "usage" of the language which is harmful to the quality of debate (and, potentially, to the community in question). I believe you that you didn't intend to use the language in such a way, but you did. Be it sloppiness, dyslexia, or whatever that caused it - you crossed the line and I reacted to that. Your phrasing could result in the damage to the community, but honestly, I'm not that interested in that; on the other hand, your phrasing did influence the quality of the discussion negatively, which is what interests me much more. Hence the reaction.
What I'm wondering about is why do you defend your "usage of language" so much. Is it really the only way you can express yourself? Is it really impossible for you to use the language in a better way? If you are handicapped somehow and really can't perceive the difference between "censore" and "censor", then I'm sorry, I won't say a word. On the other hand, if you are capable of that, then I honestly can't understand why do you insist on writing comments as sloppy as yours.
> python 3 (without any library or optimization) was faster than compiled nim to count words on a moderately large text.
Do you still have examples around? I haven't used Nim yet, but it could be interesting to take a look at something like this to understand what happened.
I can check it later when I am back at home but since I regularly clean my projects & prototypes folder I do not think I kept it.
The implementation was quite straight forward in both languages: count words and then some statistic counting. It made me think that Nim will end up making me think all the time in the CPU and the compiler in the same way I did when I programmed C (and still high level languages beat the things by achieving much faster cleaner designs/prototypes/high level patterns, etc).
To be fair in my initial criticism, I guess a highly skilled Nim developer could beat python on a restricted environment, and in high level async processes both might differ in less than 1% in performance matters; but my code was really trivial and a straight forward iteration.
I'm just guessing here, but did you compile Nim in debug mode? (nim c filename.nim)
From my experience, compiling files in release mode (nim c -d:release filename.nim) makes similar tasks run 10-100x faster than Python (usually around 30x for my use cases), and it doesn't require "highly skilled Nim developer" as you mention in your reply.
sorry, I cannot tell it anymore since that was long time ago, the python version probably had a generator; also remember that python's IO and string optimizations are written all in C.
> * python 3 (without any library or optimization) was faster than compiled nim to count words on a moderately large text.
I'm sure many other commenters have singled out this comment, but do you have an example? I find this quite hard to believe. Surely this would have manifested elsewhere and people would have pointed it out ages ago? Nim compiles (or transpiles, if you prefer) to C/C++, after all.
It was very straightforward code looping, counting and storing strings in memory and writing to a file, after 2 years or more I do not keep the code anymore, sorry. Looking in perspective my guess is that the optimized C runtime of python (IO and optimized string references) competed against Nim's bare strings.
it's a mainstream design choice on most of programming languages for several reasons, like security or heavy optimizations. If the language is so focused on constrained environments that might make no sense since the developer will be anyway counting bytes in their minds.
> Caveat: for reference types, immutability is shallow (you cannot change the reference but you can mutate the reference content).
“Shallow immutability” is not just a “caveat” — it’s a complete abuse of the word “immutability”.
If you can in-place modify the interior of a so-called immutable value in any way (possibly excepting code within some kind of “unsafe” blocks), it is by definition not immutable. Immutability is a pure, all or nothing kind of thing.
That you are trying to present immutability as synonymous with C++ style “const”ness perhaps reinforces the parents’ post that Nim is not friendly or even aware of the functional paradigm of programming.
But unlike others, I think it’s okay that it doesn’t support immutable variables. It certainly doesn’t outright condemn the language. However, let’s not pretend it’s something that it’s not.
Nim const are compile-time constants, it's completely different from C++ const.
I don't agree on immutability, just like you have shallow copy and deep copy, you have shallow immutability and deep immutability.
Also functional programming also distinguish pure (Haskell, Idris, ...) and impure functional programming (Ocaml, ...).
Allowing side-effect through reference doesn't mean that a language is hostile to functional programming. It just means that it does not enforce purity.
In my humble opinion on language design, if the main language favours a paradigm or style, the libs will do it even worse although some programming languages gave weird reimplementations of their whole stdlib in a different paradigm it is not the rule. C will be C no matter how much MISRA certifications are sold.
For example, kotlin is very promising language on the paper, but in the reality it is being developed by people who kept a Java mindset and way to structure problems and code (and they repeat same concepts and ideas as they do in java, for example calling DSL to every single piece of nested code).
>After I realized about python was easily beating Nim in [speed]
It is certainly not generally the case that Python beats Nim in speed, not even close. I would imagine something was wrong with your implementation or you hit some weird Nim bug or edge case.
It could be, but remember that python optimizes a lot IO and string manipulation (runtime in C). Based on how the feature list has changed perhaps I tried Nim even earlier than what I said. I also did not want to look for any optimizations since I just used bare constructs and no libs.
Hash tables in nim require pulling in the standard library and are built-in in Python. If you didn’t even “import tables”, you were likely comparing O(1) apples to O(n) oranges.
- As far as I know Jester is the go-to for your webservers and you could use the httpclient in the standard library.
- This is true and there are plans to improve it, if you have any feedback on what could be clearer, you can share your thoughts here: https://forum.nim-lang.org/t/4523
Jester is great if you can ask the author why does it do what is does. There are lots of implicit stuff going on and I had no time to figure out why the server starts up once I create routes.
Seconded, but I had the same problem with Elixir and Plug/Phoenix. It looks like the communities of new languages with macros need some time to mature and settle on some kind of style guide for when and how to use them. In all the Lisps I know - Clojure, Common Lisp, Emacs Lisp, Scheme, Racket - the use of (new) macros is discouraged for the most part (at least on the surface, I'm not counting using `loop` in CL or `for` in Racket). It will get much better with time, I think, but I guess there is some truth to people saying that including macros in the language can be "dangerous" :)
I agree also on the point about documentation, this practice was also extended to the community modules (but everything was new and hacky so I thought it was OK, but it ended up being the rule a the ecosystem).
If you develop a new piece of software, especially a new language, documentation should be there so that the users can get in as fast as possible. I think Elixir is a great example in this regard that Jose paid attention to this feedback early and there is decent documentation for most of the things nowadays (minor exceptions). I have limited time and there are so many new languages, I will go with the one which has the lowest entering barrier.
Mutable strings: That depends on the type of application you're doing. In my area, gamedev, it is better that everything is mutable by default and you optin for immutable, since games normaly deal with structures the mutate every frame. In that scenario it is normal to have immutable things getting in your way more than the other way around.
* A return variable within procedures that works in the same fashion as an assembly routine with a registry
* Mutable strings
* Mutable everything
* Hate speech against functional concepts in the community (with all the related biases that this brings)
* Some arrogant community members were tolerated just because they wrote popular blog posts on Nim implementing a fashionable pet project.
* no clear consistent design direction
* too many pragmas
* too many pascal syntax mixed with other language syntaxes
* no module namespacing
* modules worked not much better than C libraries... (I am generalizing)
* poor ecosystem made out of incomplete mutable libraries
* python 3 (without any library or optimization) was faster than compiled nim to count words on a moderately large text.
After I realized about python was easily beating Nim in spead and readability only with the standard library without any optimisation on python's side (and Nim being fully compiled), my interest on Nim went down to 0. I thought there were other places were I thought I could better invest my time.
Did something from that list changed? is there any reason to look at Nim again in 2019? did someone here had a better or different experience than mine?
EDIT: format, reworded sentences, expanded opinions