This is very nice since it is progress towards 2.0 and a LOT of bugs were fixed. Kudos to the contributors! The element of novelty in this case are the error messages (which are very precise although not too easy to parse). In the meantime if you are curious how being on HN homepage affects traffic, analytics of nim website are public: https://plausible.io/nim-lang.org?period=30d
I love Nim so much. I really hope some big company decides to use it as their workhorse language - it feels like the only thing holding it back is the lack of corporate 'buy in'. Most similarly good languages (except F# maybe?) seem to get lucky with becoming a poster boy for at least one company.
>Most similarly good languages (except F# maybe?) seem to get lucky with becoming a poster boy for at least one company.
This one I still can't wrap my head around. F# basically was the source of almost all innovation in C# and C# still is missing some features and was not designed in the same way as F# so a lot of the features they "stole" feel tacked on.
Microsoft should have just made F# the C# successor.
> Microsoft should have just made F# the C# successor.
You underestimate the importance of compatibility and familiarity for existing developers. You can show C# code to any C++, Java or even JS programmer and expect them to grasp the idea of what's going on very quickly. This is a big deal and should not be discarded lightly
I had a brief look at F#, it didn't fit my mental model and I looked away. Meanwhile I do like using the tacked-on functional features in traditional languages because it allows me to get the benefits when it fits what I'm doing instead of having to fully buy in.
F# is such a nice language. A great modern ML language on the .net runtime with full MS package support that's pretty awesome. But unlike something like Scala on the JVM F# is so simple and straightforward, it has a lot of features without feeling bloated. The fact that MS has just abandoned F# is disappointing.
Yup, corporate buy in is a big deal. Years ago I tried using Nim for a network daemon, but the sheer lack of even the most basic http libraries prevented me from doing it and I went with go.
The library situation is a bit better now. But without a big company contributing in terms of libraries, the language usage will just be very low.
Programming language adoption -- like the adoption of many technological products -- is usually really fast. With the possible sole exception of Python, all programming languages, popular and unpopular alike, have reached the general ballpark (i.e. high/mid/low) of their all-time peak market share within 5-10 years. Dark horses are very, very rare.
C++ was designed in the late '70s-early 80's and reached peak popularity in the mid-to-late '90s. JavaScript appeared in the mid-'90s and didn't see broad adoption until about the '10s. I would say that the norm is for peak adoption to happen at around the 10-15 year mark of original release. Languages that get adopted faster than 7 years are unusual, and it indicates that they came out at highly opportune times to address specific needs. I'm thinking in particular of Java and Rust, for example, which both reached critical masses of adoption very quickly.
I can't see how there should be a reliable pattern in language usage like that. Javascript is more used that ever - who knows were the all-time market share peak is - but we're well beyond your 5-10 year time frame. Could you name any languages that actually have this pattern? Julia maybe.
In general you are correct. However, language adoption can skyrocket when some new library/framework arrives which has a compelling reason to switch (e.g. Rails for Ruby)
Companies base their choice of tools on how easy is to find developers to hire, therefore Nim and other similarly young but very powerful/optimized languages (Crystal, Zig, ...) need many independent developers, who can base their choice purely on technical merits and personal taste, to use it and put it into their resumes before the corporate world can notice and add them into their list of accepted tools. It's a quite slow process though.
I am in a position to do this and I picked kotlin instead as the tooling is not good enough yet. Without a good IDE experience you lose some of the productivity that nim potentially offers.
This longer time is because extra care is being taken into having a smooth transitions (for example important libraries have been tested to work on nim v2, e.g. we made sure nimib was working with v2 in early Feb: https://github.com/pietroppeter/nimib/releases/tag/v0.3.6)
Some background: I spent years in C++, then many years in Java, Ocaml, Python, Rust and even APL - everything is for production. My last pet-project was on Rust also, and it took about 2+ years and I felt pretty depressed about IT at all.
One of the part of the project (feed collector) I tried to write in many languages to compare. One day I downloaded Nim - did not expect anything at all - just wanted to try async and ... in about 2 hours (on new language for me) I had the same functionality I spent 2 weeks in Rust. More interesting - it was about 30% faster than Rust solution.
I rewrote full (2 years+) project in Nim in 3 weeks. I understand that I knew good architecture for the second implementation, but 3 weeks is good anyway.
Did a lot of pet-projects, I use it for small prod tools or research if it is possible.
For new Nim's user I would describe it like python with speed of C-lang. But later you will find that it is not another python, it is its own language with a lot of powerful things like templates, macros, very good interop with C (that is why libraries are not a problem most of the time) and etc.
Also, I would like to mentioned that I was impresses how much the Nim is perfect shape with quite small team of core contributors compared to many other languages. There are some bugs, of course. nimsuggest (main thing for LSP) is not in the perfect shape. But I did not have any feelings of unfinished product like Pony-lang, Crystal and etc
I noticed Nim allows using the Go GC as an option. How does this work? Does it compile into Go as a target language? Or can it link with Go's (ever changing) ABI? Or is the Go GC available as a standalone C lib? I'm just curious how this works...anybody know?
EDIT: I think I found it - looks like it actually isn't new: https://forum.nim-lang.org/t/1278. Sounds like the answer is: Links via GCCGO to their channel implementation. Compatible GC was written in Nim to go with it.
OK, so we have languages for nearly every niche now; Zig has it's allocator thing and goes with C very well, Go has goroutines and channels and CSP, Python has data science, Java has support/libraries for everything, etc.
Let me suggest a new one: a language which is top-dog in it's language interoperability. Imagine a language that can do nearly nothing except glue together code from other languages. Maybe you want to call some Java code from some Go code from some Nim code from some Python code from your C program: this language would do that for you somehow.
Another idea for that would be GraalVM’s Truffle. It’s not a language, more of a universal VM, but it can actually already just eval some python code, use the resulting code from Java and pass it on to JS. It also has support for any LLVM language, so C can be invoked from/be invoked from any of the aforementioned languages. And it can even optimize across language boundaries, pretty incredible.
ha - I've had my "interop" language in my head forever. FFI primarily by generating code directly into every lang (haxe-style), but ideally with a better lang behind it (imagine Python and Rust had a baby). Oh if I had the time...would be fun.
The only situation I can imagine this causing a problem in your codebase is if you intentionally want to mix camelCase and snake_case in your codebase and these 2 meaning different things. So if you don't enforce in your codebase a specific code style practice and you would like someFunction and some_function to coexist and mean different things, then yes. Nim's approach is problematic for you.
If you enforce a code style or, if you don't but you would convene that someFunction and some_function should mean the same thing in your codebase. Then nim's approach should be transparent to you.
It also makes it harder to grep. If you're on a team of 10 devs someone could have accidentally forgotten an underscore sometime last year. So you can't just grep for 'ready_for_upload', you have to use 'ready_?for_?upload'
It would be one thing (but still a weird feature that calls the rest of their decision making into question) if it normalized fooBar into foo_bar (or the opposite). But that's not what it actually does, it normalizes both into foobar, which introduces new ambiguities. In fact, you can often end up with the opposite meaning! For example, a few Swedish examples:
- hand tvättas (wash your hands) != handtvättas (wash by hand)
Another situation is when you have to interface with some other language that doesn't have this feature and where nameLikeThis and name_like_this both exist and mean different things. Thus requiring you to work it around with a third naming convention.
> The only situation I can imagine this causing a problem in your codebase is if you intentionally want to mix camelCase and snake_case in your codebase and these 2 meaning different things.
This is literally idiomatic Python style! Classes are TitleCase and everything else is snake_case.
I have also used a mix of camelCase and snake_case for different purposes, eg in Haskell where conventions are mixed (and I am far from an expert), I've written names like "fooBar_prev"
I'm not sure I understand the rationale of it if using a consistent naming approach (best practice) renders it transparent, and compiler warnings alert you to instances where one is using e.g. my_var and myVar. Seems like the capability is there but the typical advice and compiler both warn against taking advantage of it. Just seems like a footgun to me. What am I missing?
This is done a lot in Python Libraries the module with lower_case and class name with TitleCase . In Nim's Case (No Pun Intended) it is a fatal mistake.
Carmack's tweet seems like more of a thought provoking question than an indictment of case sensitivity. I'm not sure I am convinced that a child stumbling over case sensitivity is a smoking gun. I just explained it to my nontechnical partner and before I had finished and proposed a "what do you think?" kind of question, she had given a "oh,hmm" to the idea that "abc" and "ABC" might mean the same thing when used as variables. Again, no smoking gun here either.
Plenty of programming languages have "did you mean xxx?" in error messages. Plus using IDEs means you will mostly autocomplete identifiers anyway. I don't buy it.
I agree. It's one of my biggest gripes with the language. It has big effects on greppability. And by extension, it also has effects on search-engines. Both large ones like Google, and small ones like Github's or StackExchange's built-in engines. Even browser-search on an API document could be problematic.
If I'm looking for some example code that uses my_testfunction(), I can't just search for "my_testfunction nim". Instead I have to add MyTestFunction, my_test_function, MYTESTFUNCTION, etc. The case-insensitivity isn't really a big deal, but the underscore-insensitivity is.
If I'm honest, I think this is a big problem for adoption of the language. It's incompatible with a lot of search-engines, and weird to anybody coming from any other programming language. Nim should take advantage of the 2.0 release to do a compatibility break in this area, maybe with a compiler flag to enable the legacy behavior.
Your argument applies to style sensitivity as well to be fair - do you search for 'MyTestFunction' or 'my_TestFunction'... or was it 'My_TestFunction', maybe 'm_Y_tEsT_fUnCtION'?
Style insensitivity lets you automate your local code (and/or through CI) to consistency for easy searching, even when external libraries YOLO their own style.
> It's incompatible with a lot of search-engines
Google and search engines are case insensitive, and mostly ignore underscores too. Let's be honest, how often would you just search for 'testfunction libraryname' on the web and get the signature you need?
My experience from using the language in production for years is that case insensitive searches will find what I want in Nim code specifically because no one can use case/underscores to make things make unique. Instead, the language uses overloading through the type system to distinguish things. This is a far more succinct, safe, and expressive way of writing code from my perspective.
It's worth noting that the first letter of an identifier is case sensitive, with the convention for types to start with a capital letter. So, you can write 'type Test = object' and 'proc test(t: Test)', then use them with 'var test: Test; test(test)' without any ambiguity, and with code completion/jump to source in VSCode (and others).
If you then add 'proc test()' with no arguments, it's still unambiguous because the functions have different signatures, so you can then write 'test()' and your second function is called.
If something is ambiguous, it's a compile time error. If you want, you can prefix modules like Python, but there's never any need. If you have two libraries with the API, same types, and function signatures (such as using two async libraries in the same program), you can just slap a generic '[T]' so it's lazily instantiated at the call site and move on.
IMHO relying on casing/underscore to distinguish identifiers is objectively worse than using the type system to statically and unambiguously prove your intent, and normalising names removes a class of identifier confusion bugs to boot. Even style guides in case sensitive languages beg us not to use case and underscores to disambiguate symbols for the confusing code it creates, and to be honest, I've yet to see a compelling argument in favour of case sensitivity beyond simply being what people are used to.
Most of my complaints about this went away with --styleCheck:error. You might already know about this flag, but some people do not. Most projects I have found stick pretty closely to NEP1.
I cant think of a single situation in which I would want take_action() and Take_Action() to do different things inside of a program. What reasonable purpose would naming things that way serve?
I see it as a mandated style checker built into the language.
Nobody wants codebases with different take_action() and Take_Action() functions. That's a straw man.
The issues are:
1. Difficult to search code. Even just case insensitivity makes this worse because often you do have names that only differ in case (but in an acceptable way, e.g. they're different kinds of thing, or namespaces). But ignoring underscores makes it much much harder - now every search needs to be a regex.
You can say "use an IDE!" and you absolutely should but you still sometimes need to search with dumb grep style tools.
2. Case insensitive rules are always more complex and difficult to remember. Where do they apply? All identifiers or just variables? What about keywords. Nim's rule is especially complex. It adds cognitive load.
3. Extra bike shedding. I imagine they added it to avoid bike shedding? But it will have the opposite effect. They should have just made a language wide convention like Rust. Nobody debates case style in Rust or indentation style in Go because the tooling and community pretty much force one style.
I fully anticipate a Nim linter that bans style variation from the canonical one. If that doesn't exist already.
IMHO from a theory POV, it violates the/my principle of least surprise. Compilers are typically strict and I'm ok with that - my mental models of programing are built around that unforgivingness and I like it, because if I play by the rules, I know there'll be no surprises (ideally). When the rules are relaxed, I have to remember more stuff. It's easier for me to know that ABC is ABC, and never abc or a_b_c.
I think I remember reading early remarks from the Nim team that you can opt-in to the symbol sensitivity but it's a marker comment per-file, or some kind of DIY preprocessor which does the same. I'd be happy if it was a CLI switch.
All that said, and in practice, clearly a lot of people are fine with this and even like it. I'd much rather Nim exist with this (IMO) oddity than not at all.
I have extensively used Nim for the past 6 years, and it has never been an issue. I have seen codebases where someone wrongly capitalized a variable identifier, which results in a compiler warning being raised. So no harm done.
I was annoyed by it at first, but got past that, and now don’t think too much about it. With tooling support (mainly lang server and nimgrep) I haven’t found it to get in the way, and have come to appreciate the flexibility it provides.
Same. Was strongly considering getting into Nim, but screw that, not interested in needing special tooling for something as basic as reliably grepping Nim code, there's too many other languages out there.
In this thread there are people who say "a convention is enough", but then don't give enough credit to the Nim convention. Maybe you are imagining a Nim library abusing this ability, and the same developer writing all different versions allowed: write_file, writefile, writeFile, w_ri_tefil_e...
Nim developers are as smart as any other, and they like and write clean codebases adhering to the convention in NEP1. The ability to mix cases is used to fix libraries without having to disrupt their users.
I've seen this kind of complains over and over: a new language emerges (e.g. Python 20-30 years ago), and what people finds the absolute showstopper is the indents instead or braces, a minimal part of the language that should not bother a competent programmer at all. The same people that were writting old PHP or old Perl, go figure, complainig that Python whitespace is ugly.
This one I still can't wrap my head around. F# basically was the source of almost all innovation in C# and C# still is missing some features and was not designed in the same way as F# so a lot of the features they "stole" feel tacked on.
Microsoft should have just made F# the C# successor.
You underestimate the importance of compatibility and familiarity for existing developers. You can show C# code to any C++, Java or even JS programmer and expect them to grasp the idea of what's going on very quickly. This is a big deal and should not be discarded lightly
their target audience does not want this
The library situation is a bit better now. But without a big company contributing in terms of libraries, the language usage will just be very low.
Hearing again I cannot chuckle when Araq says: Nim v1 is good at everything, Nim v2 is supposed to be better at everything.
Back then it was supposed to come out in 2022 and indeed a RC1 came out in Dec. In the blogpost for RC1 you find the desciption of all new features: https://nim-lang.org/blog/2022/12/21/version-20-rc.html
This longer time is because extra care is being taken into having a smooth transitions (for example important libraries have been tested to work on nim v2, e.g. we made sure nimib was working with v2 in early Feb: https://github.com/pietroppeter/nimib/releases/tag/v0.3.6)
One of the part of the project (feed collector) I tried to write in many languages to compare. One day I downloaded Nim - did not expect anything at all - just wanted to try async and ... in about 2 hours (on new language for me) I had the same functionality I spent 2 weeks in Rust. More interesting - it was about 30% faster than Rust solution.
After it, I can just show the picture: https://user-images.githubusercontent.com/4949069/229308266-...
I rewrote full (2 years+) project in Nim in 3 weeks. I understand that I knew good architecture for the second implementation, but 3 weeks is good anyway.
Did a lot of pet-projects, I use it for small prod tools or research if it is possible.
For example I wanted to extend atop functionality, and I wrote my own ttop: https://github.com/inv2004/ttop
For new Nim's user I would describe it like python with speed of C-lang. But later you will find that it is not another python, it is its own language with a lot of powerful things like templates, macros, very good interop with C (that is why libraries are not a problem most of the time) and etc.
One awesome project is https://github.com/jmgomez/NimForUE
EDIT: I think I found it - looks like it actually isn't new: https://forum.nim-lang.org/t/1278. Sounds like the answer is: Links via GCCGO to their channel implementation. Compatible GC was written in Nim to go with it.
Let me suggest a new one: a language which is top-dog in it's language interoperability. Imagine a language that can do nearly nothing except glue together code from other languages. Maybe you want to call some Java code from some Go code from some Nim code from some Python code from your C program: this language would do that for you somehow.
Another idea for that would be GraalVM’s Truffle. It’s not a language, more of a universal VM, but it can actually already just eval some python code, use the resulting code from Java and pass it on to JS. It also has support for any LLVM language, so C can be invoked from/be invoked from any of the aforementioned languages. And it can even optimize across language boundaries, pretty incredible.
If you enforce a code style or, if you don't but you would convene that someFunction and some_function should mean the same thing in your codebase. Then nim's approach should be transparent to you.
- hand tvättas (wash your hands) != handtvättas (wash by hand)
- sjuk gymnast (sick gymnast) != sjukgymnast (physical therapist)
- sjuk sköterska (sick nurse) != sjuksköterska (hospital nurse)
- lång hårig (tall and hairy) != långhårig (long-haired)
- sjö nära tomt (lake near a house) != sjönära tomt (house near a lake)
Here's one illustration: https://github.com/nim-lang/RFCs/issues/456#issuecomment-111...
We have partial case-insensitivity in PHP. Can't say I'm very fond of it, but I'm ambivalent as long as it's not abused.
This is literally idiomatic Python style! Classes are TitleCase and everything else is snake_case.
I have also used a mix of camelCase and snake_case for different purposes, eg in Haskell where conventions are mixed (and I am far from an expert), I've written names like "fooBar_prev"
Also, John Carmack: https://mobile.twitter.com/id_aa_carmack/status/159256093820...
If I'm looking for some example code that uses my_testfunction(), I can't just search for "my_testfunction nim". Instead I have to add MyTestFunction, my_test_function, MYTESTFUNCTION, etc. The case-insensitivity isn't really a big deal, but the underscore-insensitivity is.
If I'm honest, I think this is a big problem for adoption of the language. It's incompatible with a lot of search-engines, and weird to anybody coming from any other programming language. Nim should take advantage of the 2.0 release to do a compatibility break in this area, maybe with a compiler flag to enable the legacy behavior.
Style insensitivity lets you automate your local code (and/or through CI) to consistency for easy searching, even when external libraries YOLO their own style.
> It's incompatible with a lot of search-engines
Google and search engines are case insensitive, and mostly ignore underscores too. Let's be honest, how often would you just search for 'testfunction libraryname' on the web and get the signature you need?
My experience from using the language in production for years is that case insensitive searches will find what I want in Nim code specifically because no one can use case/underscores to make things make unique. Instead, the language uses overloading through the type system to distinguish things. This is a far more succinct, safe, and expressive way of writing code from my perspective.
It's worth noting that the first letter of an identifier is case sensitive, with the convention for types to start with a capital letter. So, you can write 'type Test = object' and 'proc test(t: Test)', then use them with 'var test: Test; test(test)' without any ambiguity, and with code completion/jump to source in VSCode (and others).
If you then add 'proc test()' with no arguments, it's still unambiguous because the functions have different signatures, so you can then write 'test()' and your second function is called.
If something is ambiguous, it's a compile time error. If you want, you can prefix modules like Python, but there's never any need. If you have two libraries with the API, same types, and function signatures (such as using two async libraries in the same program), you can just slap a generic '[T]' so it's lazily instantiated at the call site and move on.
IMHO relying on casing/underscore to distinguish identifiers is objectively worse than using the type system to statically and unambiguously prove your intent, and normalising names removes a class of identifier confusion bugs to boot. Even style guides in case sensitive languages beg us not to use case and underscores to disambiguate symbols for the confusing code it creates, and to be honest, I've yet to see a compelling argument in favour of case sensitivity beyond simply being what people are used to.
Can confirm, it single-handedly kept me away from the language.
> Nim should take advantage of the 2.0 release to do a compatibility break in this area, maybe with a compiler flag to enable the legacy behavior.
No thanks, I don't want inconsistent naming conventions in my code.
I see it as a mandated style checker built into the language.
The issues are:
1. Difficult to search code. Even just case insensitivity makes this worse because often you do have names that only differ in case (but in an acceptable way, e.g. they're different kinds of thing, or namespaces). But ignoring underscores makes it much much harder - now every search needs to be a regex.
You can say "use an IDE!" and you absolutely should but you still sometimes need to search with dumb grep style tools.
2. Case insensitive rules are always more complex and difficult to remember. Where do they apply? All identifiers or just variables? What about keywords. Nim's rule is especially complex. It adds cognitive load.
3. Extra bike shedding. I imagine they added it to avoid bike shedding? But it will have the opposite effect. They should have just made a language wide convention like Rust. Nobody debates case style in Rust or indentation style in Go because the tooling and community pretty much force one style.
I fully anticipate a Nim linter that bans style variation from the canonical one. If that doesn't exist already.
I think I remember reading early remarks from the Nim team that you can opt-in to the symbol sensitivity but it's a marker comment per-file, or some kind of DIY preprocessor which does the same. I'd be happy if it was a CLI switch.
All that said, and in practice, clearly a lot of people are fine with this and even like it. I'd much rather Nim exist with this (IMO) oddity than not at all.
Nim developers are as smart as any other, and they like and write clean codebases adhering to the convention in NEP1. The ability to mix cases is used to fix libraries without having to disrupt their users.
I've seen this kind of complains over and over: a new language emerges (e.g. Python 20-30 years ago), and what people finds the absolute showstopper is the indents instead or braces, a minimal part of the language that should not bother a competent programmer at all. The same people that were writting old PHP or old Perl, go figure, complainig that Python whitespace is ugly.