1. 39
  1.  

  2. 18

    Shameless plug - I interviewed Andreas, the creator of Nim, about his philosophy and design choices here: https://sourcesort.com/interview/andreas-rumpf-on-creating-and-growing-nim

    Might be an interesting read for people who are thinking about using Nim and wondering how it compares to the C family, Python, Go, etc.

    1. 6

      I love his final words:

      creativity is often the result of constraints.

      Nice small interview by the way :)

      1. 4

        Very interesting read. Definitely makes me more interested in trying out Nim. He said he works full-time and has two other programmers working on it too. Where does the money come from for this?

        1. 9

          Where does the money come from for this?

          One year ago Nim partnered with Status, see the article about this partnership.

        2. 0

          Nim’s long development process and growing community also mean that Nim is mature

          A-ha-heh… um… When I looked, the package/library ecosystem doesn’t hold a candle to, say, RubyGems or npm. (Not hating on Nim, just saying.)

          1. 3

            Maybe mature doesn’t mean that there is a package for everything, but rather the packages are not buggy.

        3. 10

          I’d love to see some code snippets to help me understand what made Nim so effortless as compared to a ‘scripting’ (god I hate that term :) language.

          1. 7

            I can give a couple small examples of toy tings I’ve done at work:

            This is a program that prints out each directory in $PATH on it’s own line.

            import os, strutils
            
            var path = getEnv("PATH")
            echo path.replace(";", "\r\n")
            

            This is a program the spits out 5 lines of the character “-”, with a specified background color.

            import terminal, strutils, os, tables
            var color = "green" 
            
            var colorTable = newTable[string, BackgroundColor]([
                ("black", bgBlack),          
                ("red", bgRed),                 
                ("green", bgGreen),               
                ("yellow", bgYellow),              
                ("blue", bgBlue),                
                ("magenta", bgMagenta),             
                ("cyan", bgCyan),                
                ("white", bgWhite)
            ])
            
            
            if paramCount() > 0: 
                color = paramStr(1)
            if color.toLower in colorTable:
                setBackgroundColor(stdout, colorTable[color], false)
            
            for i in 0..5:
                echo "-".repeat(terminalWidth() - 1)
            resetAttributes(stdout)
            

            The key point as far as executables are concerned is that, unlike Go, C#, or Java, is that both of these files are one invocation of nim c filename.nim away from being executables that I can then copy into my $PATH. Compilation times for me are under 10 seconds, which isn’t instant, but is faster than Go or C# in this case. VS Code gives live error updates as well.

            Go, for comparison, requires that you have a func main(), and that there is only one instance of main in a given folder. C# requires either MSBuild or understanding how to pass dependencies to csc.exe, and then you usually have to have a lot of DLLs around. Python and Ruby can both use Shebang files to achieve similar concision, but then if you have multiple files, shebang lines don’t bundle them up for you, and you’re outside of the easy/obvious path for executing code in those languages.

            1. 7

              Compilation times for me are under 10 seconds

              Something is wrong here. If it takes multiple seconds to compile these examples (or any similar relatively simple “script”), can you check with nim -v if your compiler is compiled in the release mode? You should see the line active boot switches: -d:release in there.

              I have a ~10 year old CPU and I have never seen such slow compilation times.

              1. 4

                These compilation times are on Windows, running inside the VS Code PowerShell prompt.

                I’ll check more next time I’m editing the programs, but like I said, they feel pretty zippy compared to Go’s compile times.

                1. 1

                  running inside the VS Code PowerShell prompt

                  Isn’t that a Javascript application? Does the compiler run in Javascript as a result or does it run it as native code? I’m curious since I figure Nim-to-native-code would be best way to benchmark the compiler on a hunch that they optimized the Nim-to-C-for-LLVM part the most.

                  1. 1

                    There sounds like something really wrong with your Go setup…

                    1. 2

                      Just fired up a Windows VM to see if Go compile times on it were awful, still well under a second for the 10 line example program (reading path, etc).

                2. 3

                  Compilation times for me are under 10 seconds, which isn’t instant, but is faster than Go or C# in this case.

                  I don’t know about C#, but I’d be surprised if compiling a similar go program took 10s or more.

                  Doesn’t take away how good an alternative Nim can be for short programs like these.

                  1. 2

                    Go is one invocation of go build filename.go away from being an executable that you can copy into your path.

                    package main
                    
                    import (
                    	"fmt"
                    	"os"
                    	"strings"
                    )
                    
                    func main() {
                    	path := os.Getenv("PATH")
                    	fmt.Println(strings.Replace(path, ":", "\r\n", -1))
                    }
                    

                    Which compiled on my machine in 0.239s total. I have been a fan of/follow nim since it was nimrod, it is awesome, just wanted to clear up that point.

                    1. 1

                      For reference, the nim code

                      import os, strutils
                      
                      var path = getEnv("PATH")
                      echo path.replace(":", "\r\n")
                      

                      took .885s to compile (more than 3x slower than Go).

                      1. 2

                        Ah, perceptions for me might be off. The Nim compiler is a lot noisier than the Go one.

                        1. 2

                          Could also be a Windows thing – never used the go toolchain on windows.

                          1. 1

                            Yeah. Well, I’ve almost never witnessed subsecond compiles for the Go or Nim toolchains. My powerful hardware is on Windows, where file access seems to be just slow enough to make things slower. My Linux hardware is an oldish VPS that I probably need to migrate to a newer machine, and which is sharing hardware with other VMs.

                      2. 0

                        Now, can you have 3 of those, all with “func main” in them, that can depend on other files in the same folder, without having to massage how you ask Go to build the files?

                        It’s not that you can’t make small things in Go, just that it’s easier to do so in Nim. 10 lines vs 3 lines, in this case.

                        At any rate, if you like Go, feel free to keep using it. I happen to like Nim’s ergonomics better.

                        1. 1

                          10 lines vs 3 lines, in this case.

                          Of which I ended up writing 4 (could have been 3 if I used an auto-closer for {}). With my very basic tooling, in an esoteric editor (Kakoune), imports were added automatically, as was package main. So in terms of ergonomics, it was basically a wash.

                          Now, can you have 3 of those, all with “func main” in them, that can depend on other files in the same folder, without having to massage how you ask Go to build the files?

                          No… but why would I want to? I mean, as criticisms go, I don’t entirely understand this one. The use case is writing multiple files that act as both entry-points and libraries in the same directory with circular dependencies?

                          1. 2

                            It’s less “Go sucks” and more “I like how Nim structures its projects in the small better than Go”

                            I don’t think Nim makes it easy to get circular dependencies.

                            For me, it’s like getting a /cmd directory without having to manange two levels of directory heirarchry to do so.

                            My first real project in Nim was https://idea.junglecoder.com/view/idea/277 which was half the lines of Go version. That was mostly down the Nim standard library is containing a type to do what I wanted (a key/value collection that remembers insertion order). In Go I had to roll my own.

                            I will fully admit to not being the world’s most effective Go programmer. Nim fits how I think a bit more comfortably, and it puts enough less friction into building small things that I’ve made a lot more of them in Nim of late.

                      3. 1

                        The key point as far as executables are concerned is that, unlike Go, C#, or Java, is that both of these files are one invocation of nim c filename.nim away from being executables that I can then copy into my $PATH. Compilation times for me are under 10 seconds, which isn’t instant, but is faster than Go or C# in this case. VS Code gives live error updates as well.

                        OK this makes sense to me, and since we’re talking about preferences and subjective squishy things like what it ‘feels’ like to develop in a language, I won’t argue your point, but compare and contrast that experience to no compile step at all and I see a fairly strong argument for continuing to love my Python while respecting that these tools are all incredible in their own right and do indeed provide a considerably faster execution path for the majority of code cases.

                        1. 1

                          Indeed. If you’re wanting to run/compile at the same time, there is nim c -r filename.nim which will run it after compilation.

                          If you’re already happy with Python, however, Nim may not do anything too amazing for you, other than potentially being a bit easier to distribute, (that’s just a guess on my part, however. I’ve had issues trying to distribute python programs in the past, specifically pygame, but it’s been a while since I’ve tried to distribute python software).

                          Nim also has static typing baked in, which I like. I know python has some static typing tools built in these days as well, but yeah.

                          1. 2

                            Python’s distribution story is a known issue. There are various efforts afoot to improve things, but none of them are in core.

                            There’s no doubt that languages like Nim, Go, C/C++ and Rust have advantages in that department.

                            Tools are all about trade-offs :)

                    2. 5

                      and on the developer experience? is the compile time bearable? How’s editor integration, can there be some sort of a repl? How are the error messages? thanks

                      1. 4

                        How’s editor integration

                        I think that the most Nim developers are using VS Code. I personally use NeoVim with this plugin, which, IMO, makes the experience even better than the one in VS Code.

                        Fun fact: three core developers use three different editors: VS Code, Emacs, NeoVim.

                        1. 1

                          It has a kinda proto-repl feature called “hot code reloading”. It needs some initial setup, and doesn’t give you the typical repl experience as is, but most certainly should allow for live coding (I haven’t tried it myself yet), thus I assume it qualifies at least as “some sort of repl”? :)

                          1. 0

                            The VS code integration is quite nice. I’ve had fairly good experience with error messages. The compile time is very low, and seems to be less than Go’s compile time, at least it feels that. There can be a REPL of sorts, if you type nim secret, but it’s not a fully featured thing.

                          2. 2

                            The C-family of languages has … slow compilers

                            Was that really true in 2006 when Nim started?

                            1. 2

                              I don’t know much about Nim, but I’m pretty tired of the implication that scripting languages can’t be compiled. Nearly every well-known scripting language has a compiler; stop perpetuating 1990s stereotypes.

                              1. 5

                                It’s funny how you say “1990s stereotypes” when PHP didn’t have a compiler until 2010.

                                1. 7

                                  While a fair criticism, 2010 was nearly a decade ago. There are certainly many of us who still think of the nineties as merely a decade or so ago.

                                  1. 3

                                    One’s perception doesn’t matter, 2010 is 9 years ago (9 and a half if we consider February 2010, the release date of Hip Hop), and calling it “1990s stereotypes” to bring forward an incorrect and overblown statement is not a valid move.

                                    1. 2

                                      Perceptions definitely matter when it comes to language and communication. This is because you must communicate such that it is received by the listener’s expectations. A speaker who communicates to the listener’s perceptions will be far more effective. 90’s stereotypes for example may not have been meant to be taken so literally. Now you can say as a listener, “It didn’t work for me, I took it literally” and that’s a fair criticism, however you’re not the only listener, and not every listener will receive it the way you did.

                                  2. 4

                                    Ruby was a tree-walking interpreter until 2009 (based on this page).

                                    Python is said to be compiled but has, and will continue to have, a “Global Interpreter Lock”.

                                    @technomancy is getting way too overwrought over the imprecise but useful phrase, “compiled language”. Wikipedia: “The term is somewhat vague.” There is a useful separation here. Until we come up with a better name for it, let’s be kind to usage of “compiled language”.

                                    1. 10

                                      Python is said to be compiled but has, and will continue to have, a “Global Interpreter Lock”.

                                      These things are not in opposition to each other. OCaml has a native code compiler, and its runtime system has a GIL (a misnomer: a better name is “global runtime lock”).

                                      1. 1

                                        Interesting!

                                      2. 4

                                        imprecise but useful phrase

                                        What do you find this phrase to be useful for?

                                        You can see in the comments below that the author’s intent was not to describe programs that compile to machine language, but actually to describe programs that can be distributed as single-file executables. (which is also true of Racket, Lua, Forth, and many other languages)

                                        So it seems that even by declaring “compiled” to mean “compiled to machine language” we haven’t actually achieved clear communication.

                                        1. 2

                                          I’m actually rather interested in how you get single file executables with Lua? Is there a tool that makes it easy, or is it something out of the way?

                                          EDIT: I know how to get single file executables with Love2d, and I vaguely recall that it can be done with Lua outside of Love, but it’s certainly not an automated/well-known thing.

                                          1. 4

                                            Many people simply embed Lua in their C programs (that was the original use case it was designed for) but if you’re not doing that you can streamline it using LuaStatic: https://github.com/ers35/luastatic/

                                          2. 2

                                            You’re pointing out a second way in which it is imprecise. I’m pointing out that for me – and for a large number of people who don’t know all the things you do – it was useful since it perfectly communicated what the author meant.

                                            1. 3

                                              Oh, interesting, so you mean to say that when you read “compiled language” you took it to mean “produces a single-file executable”?

                                              This is honestly surprising to me because most of the time I see “compiled language” being misused, it’s put in contrast to “interpreted language”, but in fact many interpreted languages have this property of being able to create executables.

                                              It’s just a tangled mess of confusion.

                                              1. 5

                                                Indeed it is. I didn’t mean that I understood “produces a single-file executable.” I meant that he’s pointing towards a divide between two classes of languages, and I understood the rough outline of what languages he was including in both classes.

                                                Edit: I can’t define “compiled language” and now I see it has nothing to do with compilation. But I know a “compiled language” when I see it. Most of the time :)

                                                1. 3

                                                  Perhaps a good way to put it is “degree of runtime support that it requires”. Clearly, normal usage of both Nim and Python requires a runtime system to do things for you (e.g. garbage collection). But Nim’s runtime system does less for you than Python’s runtime system does, and gets away with it mostly because Nim can do many of those things at compile time.

                                                  1. 4

                                                    Even if a language retrofitted a compiler 20 years ago, it’s hard to move away from the initial programming UX of an interpreted language. Compilation time is a priority, and the experience is to keep people from being aware there’s a compiler. With a focus on UX, I think all your examples in this thread have a clear categorization: Perl, Python, Ruby, Racket, Lua, Node and Forth are all interpreted.

                                                    1. 4

                                                      I would frame it differently; I’d say if a language implementation has tooling that makes you manually compile your source into a binary as a separate step before you can even run it, that’s simply bad usability.

                                                      In the 90s, you had to choose between “I can write efficient code in this language” (basically C, Pascal, or maaaaybe Java) vs “this language has good-to-decent usability.” (nearly everything else) but these days I would like to think that dichotomy is dated and misguided. Modern compilers like rust and google golang clearly are far from being “interpreted languages” but they provide you with a single command to compile and run the code in one fell swoop.

                                                      1. 4

                                                        I’m super sympathetic to this framing. Recent languages are really showing me how ill-posed the divide is between categories like static and dynamic, or compiled and interpreted.

                                                        But it feels a bit off-topic to this thread. When reading what somebody else writes my focus tends to be on understanding what they are trying to say. And this thread dominating the page is a huge distraction IMO.

                                                        I also quibble with your repeated invocation of “the 90s”. This is a recent advance, like in the 2010s. So I think even your distraction is distractingly phrased :)

                                        2. 3

                                          Are you not barking at the wrong tree ? I don’t find a line where the author implies anything close to it.

                                          1. 0

                                            I was referring to the title of the post; as if “scripting ease in a complied language” is not something provided by basically every scripting language in existence already.

                                            1. 3

                                              Specifically, most scripting languages make it nontrivial to package an executable and move it around the filesystem without a shebang line. On Linux, this isn’t a huge issue, but it’s convenient to not have to deal with it on Windows

                                              1. 1

                                                OK, but that has next to nothing to do with whether there’s a compiler or not. I think what you’re talking about is actually “emits native code” so you should like … say what you mean, instead of the other stuff.

                                                1. 1

                                                  Fair enough.of a point, I suppose. Many people use “compiled” vs “interpreted” to imply runtime properties, not parsing/compilation properties, it isn’t exactly the proper definition.

                                                  I’ll try to be more precise in the future, but I would like a term for “emits native code” that is less of a mouthful.

                                          2. 3

                                            Scripting languages can be compiled, but, out of Python, Ruby, Tcl, Perl and Bash, most of them are by default written in such a way that they require code to follow a certain file structure, and if you write a program that is bigger than a single file, you end up having to lug the files around. I know that Tcl has star deploys, and I think that’s what Python wheels are for. Lua code can be wrapped into a single executable, but it’s something that isn’t baked into the standard Lua toolset.

                                            1. 3

                                              I think it would be helpful to a lot of people if you could give examples for node, Ruby, python, … Maybe you’re just referring to the wrong usage of the word compiler ?

                                              EDIT: typo

                                              1. 1

                                                For python there is Nuitka as far as I know.

                                                1. -1

                                                  Node, Ruby, and Python are all all typically compiled. With Ruby and Node it first goes to bytecode and then usually the hotspots are further JIT-compiled to machine code as an optimization pass; I don’t know as much about Python but it definitely supports compiling to bytecode in the reference implementation.

                                                  1. 7

                                                    When talking about “compiled languages”, people typically mean “AOT compiled to machine code”, producing a stand-alone binary file. Python’s official implementation, CPython, interprets bytecode and PyPy has a JIT compiler. V8 (the JS engine in Node) compiles JavaScript to a bytecode and then both interprets and JIT compiles that. Ruby has a similar story. The special thing about Nim is that it has the same ease of use as a “scripting language” but has the benefits of being AOT compiled with a small runtime.

                                                    1. 1

                                                      The special thing about Nim is that it has the same ease of use as a “scripting language” but has the benefits of being AOT compiled with a small runtime.

                                                      The idea that only scripting languages care about ease of use is just plain outdated.

                                                      In the 1990s it used to be that you could get away with having bad usability if you made up for it with speed, but that is simply not true any more; the bar has been raised across the board for everyone.

                                                2. 3

                                                  Some languages like Dart [1] have first class support for both interpreting and compiling. I dont think its fair to say something like “some random person has a GitHub repo that does this” as being the same thing.

                                                  1. https://github.com/dart-lang/sdk
                                                  1. 0

                                                    That’s the whole point; Dart has a compiler, and any language that doesn’t is very unlikely to be taken seriously.

                                                    1. 1

                                                      The point is:

                                                      Nearly every well-known scripting language has a compiler

                                                      That may be true, but nearly every well-known scripting language doesnt have an official compiler

                                                      1. -2

                                                        Also false; Ruby’s official implementation has had a compiler (YARV) since the 1.9 days; Node.js has used the v8 JIT compiler since the beginning, (not to mention TraceMonkey and its descendants) and python has been compiling to .pyc files for longer than I’ve been a programmer.

                                                        According to this, Lua has had a compiler since the very beginning: https://www.lua.org/history.html I don’t know much about Perl, but this page claims that “Perl has always had a compiler”: https://metacpan.org/pod/perlcompile

                                                        The only exception I can think of is BASIC, and that’s just because it’s too old of a language for any of its numerous compilers to qualify as official. (edit: though I think Microsoft QuickBasic had a compiler in the 1980s or early 90s)

                                                        1. 6

                                                          QuickBasic compiled to native code, QBasic was an interpreter, GWBasic compiled to a tokenized form that just made interpretation easier (keywords like IF were replaced with binary short codes)

                                                          1. [Comment from banned user removed]

                                                            1. 2

                                                              Do you really not know the different between machine code and bytecode?

                                                              No.

                                                              You seem to be under the mistaken assumption that something can’t be a compiler unless the compilation output is machine code I guess?

                                                              YARV contains both a compiler (from ruby source -> bytecode) and an interpreter for the bytecode that it compiles, just like Python does for .pyc files.