Nim is easy to write but hard to read. I often have troubles coming back to my projects and trying to understand the little differences of nim compared to my other projects in more mainstream languages.
Due to the very few medium to advanced projects out there I often struggle to follow something like idiomatic Nim or best practices.
I often find the most libs from the most prominent members of Nim community quite complex and sophisticated to my understanding.
Also I am not sure how to use threads in the best way possible. It is quite easy to sprinkle threadpool with spawn statements here and there but it is much harder to glue it together with locks and sharing data among threads.
Also I would like to just say that I am not feeling entitled to anything. I am super thankful for what you guys are doing because you are doing it very well.
At the moment I just feel like I would love to read some article about nim parallelism to understand better how to use it. I own nim in action but did not find everything in there what I was looking for.
IMHO, the Nim development and code reading experience would benefit greatly from advanced IDE features, which as of yet don't exist. (VScode is the best supported editor at present.)
Nim doesn't force you to explicitly repeat the module prefix where something comes from - if the compiler can figure it out, so can the IDE, and make this info visible to you if/when you want it without making the code more verbose.
Take for example the Xcode Swift IDE - it has a sidebar that tells you the value in each line, including explaining loops, graphical representations, etc. Nim would benefit from something like this, perhaps more than any other language. The IDE would explain exactly what's happening, including macros.
Nim is easy to write but hard to read. I often have troubles coming back to my projects and trying to understand the little differences of nim compared to my other projects in more mainstream languages.
Why do you have other projects in languages other than Nim? That's your problem right here. ;-)
If you find the most libs from the most prominent members of Nim community too complex and sophisticated to use, then report a Bug.
Believe it or not Developers cant read minds, so User feedback is very appreciated. (at least for my projects)
What is it specifically about Nim that you find hard to read, compared to which mainstream languages?
I find Nim very readable, but I admit that the metaprogramming features (Nim's most important differentiating features IMO) require me to focus more. That's not that different from other languages with macros.
Sure, IDEs can go a long way toward helping with this problem, but if I'm reading code on GitHub I often have no idea where a proc is coming from. This makes it extremely difficult to trace how the code functions without cloning it locally to open in VSCode.
Nim is not Python, Python is not Nim. But the fact that these all do the same thing:
someObject.doStuff("fun")
doStuff(someObject, "fun")
doStuff(
obj = someObject,
what = "fun",
)
doStuff someObject, "fun"
makes me have to think more than should be necessary. It's easy to say "you should pick a syntax and stick with it", but that doesn't help when reading other people's code. In general I like the UFCS but it does make the language slightly more complex.
This code from the tutorial:
type
Person = tuple[name: string, age: int] # type representing a person:
# a person consists of a name
# and an age
var
person: Person
person = (name: "Peter", age: 30)
# the same, but less readable:
person = ("Peter", 30)
Tuples are defined like an object, but with square brackets on the same line. Then when they're assigned values, they use round brackets. And instead of the traditional syntax of "var = value" they use the syntax "var: value" which in most places in Nim means "var: type".
But you can also define tuples inline, or (I think) you can define them just like objects and put the fields on new lines without the brackets at all. See point #2 above.
(Also, the error message if you accidentally use "var = value" when instantiating a tuple tells you nothing about the actual problem. I believe it just says "expected ')' but got ','" so you're left beating your head wondering what's wrong with your code that looks completely normal!)
This is particularly obvious with proc definitions. Here's a few I picked from Araq's blog:
proc newNode(next: PNode): PNode {.writes: [], new.} =
proc loginField(desc, field, class: kstring;
validator: proc (field: kstring): proc ()): VNode =
In real applications they get even worse. I know there's a lot that happens in these calls, but it takes awhile to visually process what's going on. (And pragmas are not beginner friendly, especially because they're hard to Google and hard even to find in the documentation).
Anyway, these are certainly not meant as hateful criticisms as Nim has many more things in it's favor and I have enjoyed working with it and will continue to do so! But I think there's still much room for improvement, particularly in the readability of the language.
Tuples are defined like an object, but with square brackets on the same line
You can define them exactly the same as the objects (so there you go, another example for your "more than should be necessary" syntax list :))
type
Person = tuple
name: string
age: int
What is it specifically about Nim that you find hard to read, compared to which mainstream languages?
Nim should not be compared with "mainstream languages". Looking at the top of the TIOBE Index - the first 17 are either VM, scripting, or unsafe systems languages.
Nim should be compared with languages that: compile to native binaries, come close to C performance, and offer major syntax aesthetics / developer productivity / safety benefits compared to C/C++.
Most popular examples of that are: Swift, D, Rust, and Crystal.
(I've excluded Go and Haskell for considerably lower performance, executable size bloat, and focus on other priorities. I've also excluded older members of the Pascal family for much more draconian syntax. Finally, I'm not including new "Native" variations of languages like Kotlin, which are still flaky and experimental.)
(Nim can also be compared with statically typed languages that compile to JS, like TypeScript and Dart, but that is a separate comparison. At present most Nim libraries are aimed at Native. Popularization of WebAssembly will also make Nim's JS target less relevant.)
So the questions we should be asking is: what is it about Nim's core language features that makes it harder than those similar languages.
Swift is far more focused, with fewer features (esp meta-programming) and fewer platforms (just Apple and Linux amd64, not even BSDs).
IMHO: it's about on the same level.
IMHO: Nim is easier, even without GC. With some tuning you can make Nim faster than Rust (due to choice of backend C compilers).
See this thread. Crystal is indeed much easier than Nim, while also being fast and portable...
Sure, IDEs can go a long way toward helping with this problem, but if I'm reading code on GitHub I often have no idea where a proc is coming from. This makes it extremely difficult to trace how the code functions without cloning it locally to open in VSCode.
Well, that's a trade-off, and most language designs have erred in favor of "paper readability". I think Nim's choice to lean in the other direction is a long-term benefit.
For better or worse, the trend is moving to cloud-based "compiler as a service", which would make compile time a lot less problematic. Another trend is that the hippest new code editors (ex. vscode) are being based on the Web platform, which means they can run inside the browser.
A user-script / augmented browsing script could replace code display in GitHub, GitLab, Fossil, StackOverflow, RosettaCode, etc with an iframe that contains not only syntax highlighting but tooltip hints, hyperlinks, etc.