1. 36
  1.  

  2. 11

    I am also learning Nim right now and I can relate so much with the post, especially the part about the module imports. I just dislike so much that everything gets suddenly imported into the regular namespace that I only use “import X as X” and “from X import y” so that I can keep the mentality I have built from Python

    1. 3

      Yes, this really bugs me, too. It makes autocomplete and hinting so much less useful, because after a few imports there are so many names in the namespace.

      1. 3

        Clojure used to work this way; before version 1.4 or so there was the :use section of the ns clause which brought everything in, but its use has since been strongly discouraged in favor of :require [x :as y] which is much clearer. Maybe Nim could take the same approach.

      2. 6

        I really, really want to like Nim but there are just too many oddities for me to seriously dig in. The biggest one is probably the story for writing tests: given its import and visibility rules, it’s really awkward to test functions that aren’t explicitly exported. The official position is, “don’t test those functions,” which I find somewhat naive.

        The standard library is a bit unwieldy, but maybe it’s just a maturity issue. For instance, the “futures”-like system for threads, processes and coroutine style processing are all incompatible. What?

        Finally, (and maybe this is just taste), but there’s heavy use of macros everywhere. The nim web server (jester), for instance, is heavily macro-ized which means error messages are odd and pretty severely affects composability.

        1. 4

          Don’t forget the partial case sensitivity. “Let’s solve camelCase vs snake_case by allowing you to write any identifier in either, at any time! Yay!”

          1. 2

            it’s really awkward to test functions that aren’t explicitly exported. The official position is, “don’t test those functions,” which I find somewhat naive.

            I don’t know if that’s the official position, but you can test internal functions in the module itself in the when isMainModule: block. Here’s an example.

            1. 3

              You can also include the module and test it that way. So there are definitely ways to do it. I don’t think there are any official positions on this.

              1. 1

                Hmm, I seem to remember include getting kind of messy on larger code bases – wish I could be more specific, it was a while ago. By official position I meant the responses by the developers on the Nim forum, so maybe that was a bit heavy handed.

          2. 5

            Thanks for posting this! I am just starting with Nim, coming from about 10 years of Python and JS. I’ve found it mixed going. It starts off feeling quite Pythonic and familiar, but rapidly becomes unfamiliar when looking at source code for existing libraries (which I’ve had to do a bit, as documentation or even comments tend towards zero).

            I particularly agree with you about the Uniform Function Call Syntax (thanks, I have a name for this now). It makes other peoples code harder to understand, because it seems less organised, and my own code harder to write. For example, in the nimcrypto library a bunch of encrypt functions exist with very similar signatures. Trying to use one like object.encrypt and getting the parameters wrong results in a wall of compiler errors like “did you mean this encrypt [huge type signature]?, or this one?, or this one?, or this one?, or this one?”. But there’s only one that is valid. I’ve found it pretty confusing. I’m happy to hear it might be addressed.

            1. 4

              Timely. I have Nim in Action here after skimming the tutorial (as much to support the book author as anything), and my reactions to most of the language have been “Oh, that’s convenient”. I’m drawn to the easy C/C++ FFI but overall my fiddling with the language has been pleasant.

              1. 2

                Nim in Action looks interesting. I like it that it directly dives into building things (at least it looks like that from Chapters 3 through 7). Most other books lose me at “here are 10 ways how to declare an integer”.

                1. 3

                  This is precisely what I was going for when writing Nim in Action. Super glad to see it being appreciated :)

                  I strongly believe that learning by implementing (sometimes large) practical examples is the best way to learn a programming language. Learning every single detail of the language presented through small unrealistic examples gets boring quickly.

                2. 1

                  How up-to-date is the book? It was published 2 years ago, I think, but I imagine a lot has changed in that time?

                  1. 2

                    Reasonably up to date for a dead-tree edition, it’s from 2017. I haven’t compared to the complementary ebook but those are “live” and get updates. I’ve noticed a couple changes/errata (compiler invocation option, deprecation of Aporia editor, a change to the ..< operator) but nothing significant.

                    1. 8

                      Indeed, it’s barely a year old.

                      I’ve actually added all the projects in the book to the Nim compiler’s test suite so the book should remain compatible with new versions. I’ve also asked our BDFL to not break these, so far so good :)

                      1. 3

                        Great idea on that!

                        1. 1

                          Cool. I love when the author jumps in on a comment :)

                  2. 3

                    Interesting. A lot of people have told me to check out nim whenever I say how much I like D, and I definitely see the parallels. It even has UFCS, just like D! And D also has the same thing where unqualified imports are the same as from foo import * in Python.

                    I think those unqualified imports are less of a problem in D. Unlike with Python where namespace clashes can happen at runtime and be a huge (and silent!) surprise, namespace clashes in D (and hopefully nim) are much less of a problem because they’re quickly caught at compile time. I sort of understand the problem about reading a piece of code and not having a clear indication from reading it where a certain name came from. D has an optional import foo: bar; syntax to only import the bar symbol from foo. Does nim have this too?

                    1. 2

                      import the bar symbol from foo. Does nim have this too?

                      Yes :) The syntax is very close to how you said it.

                      from foo import bar
                      

                      Here’s a real example:

                      from strutils import join
                      
                    2. 4

                      Something that doesn’t seem to be documented but I found in a GitHub issue, you can use nim c --cc:vcc to compile using Visual Studio in Windows. It only works in a “VS Tools prompt” but it saves installing MinGW if you fancy trying out Nim quickly.

                      For me, the most powerful aspect of Nim is that it targets other compilers. So for example you can just include a .c file from a .nim file and it’ll get linked in. You can then import the methods from that C file into your Nim code and call it. Same works both ways too, exposing Nim methods to C code is trivial.

                      1. 4

                        So for example you can just include a .c file from a .nim file and it’ll get linked in. You can then import the methods from that C file into your Nim code and call it. Same works both ways too, exposing Nim methods to C code is trivial.

                        How does that interact with garbage collection?

                        1. 1

                          I’ve not experimented long enough to know yet.

                      2. 1

                        I’m sure this is naive, but I’m unsure what the use-case is for Nim over Go. Maybe the optional garbage collection? Compilation to javascript, too, maybe.