Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I read the article. Still no idea what Nim is good for and why it's better than some other language.. and for which use cases?


A year ago I've started experimenting with Nim as a "faster Python" — put some declarations, change some keywords and you're ready to go — your "compiled Python" is now ~30x faster.

Recently I've used Nim for the first time for an official project at my job (at university). Instead of doing a simulation with Python+Numpy, I've decided to do it with Nim, and just plot the results with matplotlib. The whole experience was very pleasant.

Speaking of interoperability with Python, there is a great Nim library called Nimpy [0], which makes possible to use Nim as a more pleasant Cython — you can keep writing Python, and just use Nim for the intensive/slow stuff.

[0] https://github.com/yglukhov/nimpy


Did you use language interop for matplotlib, or saving/loading data files?


I saved the data in .csv and then used that, because not only did I need/want to just plot the results, but I also wanted to explore and further analyse the data in a Jupyter Notebook.


This might sound strange but Nim is good for everything. From writing backend services to creating web apps running on the client side. I've built emulators, CLI apps, a full blown forum and much more in it.

It's particularly great for systems programming tasks that require high performance and zero dependencies. For example, Status is currently writing an Ethereum 2.0 sharding client for resource-restricted devices[1] in Nim.

Nim is also awesome if you've got an existing C or C++ codebase, the interop that Nim offers is one of the best (if not /the/ best), especially when it comes to C++ interop. As far as I'm concerned no other language can interoperate with C++ libraries as well as Nim can.

1 - https://github.com/status-im/nimbus


Interesting claim. For me, D has the best C++ interoperability. Small test which D failed:

Create a std::vector<Foo> in Nim. Create some Foo objects and append them. Pass the vector to C++, create some Foo objects there and append them as well.


I think this is possible. I'm boarding a flight right now but I'll try to get back to you with an example later :)


What are Nim’s main weaknesses?


Post author here. A few things that make me sad in the pants:

- js doesn't have source maps (kinda of a big deal to me)

- some error messages are head scratchers (seem to remember trying to add things to an immutable array not being clear)

- docs could use love (eg seeing more examples of macros in action)

- devel (their nightly compiler) can be rough (e.g. i found the "strings cannot be null" cutover a bit rocky -- my own damn fault, i can't go back to 0.18 after being on 0.18.1)

- the big one I think, however, is adoption. I keep hearing "i'll just use rust or go". That's legit as they're also awesome.

nim's stdlib is massive (too big?) and there's tonnes of high quality packages out there. You won't be left thinking... well, crap, looks like I need to talk to roll this redis layer myself.

EDIT: Formatting. How does it even work?


I have implemented source maps for the js backend : https://github.com/nim-lang/Nim/pull/7508

They aren't merged yet in the upstream compiler because I wasn't sure if I wanted to refactor the jsgen with them, but otherwise they are almost there: I use them in a personal project in a forked branch


The docs issue and devel being rough are both due to the pre-1.0 status and the smaller community. It's a little bit of a catch-22; you need adoption to gain contributors but people won't adopt until there's enough contributions to make it stable.


yeah, which is usually where big companies help out. Their respect in the tech communities makes people take note of the new technology.

I really really think "underdog" is the best way to describe Nim because of this.


> nim's stdlib is massive (too big?)

It has less modules than Python.


These affect people in different ways but off the top of my head:

- No Nim v1.0 yet, despite this we do our best to create a deprecation path for everything that's possible.

- No big company like Google/Apple supporting the language.

- Community is smaller than that of Go/Rust.


A biggy is that it only really has a single developer, and no big corporate users. And relatedly the library ecosystem is relatively weak. It also has a GC, so it can't be used for really low-level stuff where that is a problem.

It's looking pretty promising though. Especially if you are a fan of python's syntax.


That is not totally true. Nim's own GC is written in Nim. You can turn the GC off.


I use Nim for Cuda, OpenCL and cache-sensitive/memory-bound multithreaded computation.

You can mix and match manual memory management and GC-managed types in the same codebase.


In this very article, which is pretty light on details, one of the few facts presented is that you can disable GC.


Agreed. I purged a bunch of stuff and still feel like I left too much in.

A couple of bonus facts for you:

- they've got an effects tracking system where you can have the compiler track (and whistleblow!) which functions are pure or not

- their multi-phase compiler allows you to read in source code at build time (from files or external programs!)

- their macro system is typesafe as it operates at the AST level

- the guy who created it will always tell you how he feels

- again with their macro system... there are FP libs, pattern matching libs, and OO libs that can "literally" transform the language to fit your preference

- and one more just for you: they don't support tail call optimization (ducks)


> - the guy who created it will always tell you how he feels

What does this mean?


I'm guessing, but I think the OP means that the Nim creator is a bit like Linus Torvalds. He will tell you if he feels your idea is silly, especially if he's argued against that idea hundreds of times already.


it sounds awesome


Two developers at least. One of whom is in this very thread. It's a concern, yes, but actually has been around for more than a decade, and is showing absolutely no sign of slowing down or going into hibernation.

I have just seen a ... competing language team spending developer time on purging the code of what they call ableism. apparently it's now offensive to talk of a sanity check ot to facetiously refer to OCD in a comment.

At least we may hope the Nim team lacks manpower for such idiocy.


Which competing language team?

All I found on Google was this gist of someone saying "sanity check" should be avoided. ("health check, too) [1], and some issues and pull requests in projects that were not languages.

One of the latter is clearly trolling to test Linus Torvalds' resolve to be polite [2][3][4][5], complaining about "ableist/saneist" terms, including "silly", on several of Linus' repositories.

You can tell it is a troll because it is just copying/pasting the exact same complaint, just changing the name of the project. It is not even bothering to change the list of alleged problematic words and their counts, so for example it is claiming that perconvert has 144 occurrences of "sanity check" when it actually has 0. In fact every single claim on that one is wrong. The only word from the complaint actually in pesconvert is stupid, which occurs one time, not the six times claimed. Second sign it is a troll is that it is from a GitHub account created just before the complaints were posted.

[1] https://gist.github.com/seanmhanson/fe370c2d8bd2b3228680e388...

[2] https://github.com/torvalds/uemacs/issues/16

[3] https://github.com/torvalds/linux/pull/595#issuecomment-4236...

[4] https://github.com/torvalds/pesconvert/issues/4

[5] https://github.com/torvalds/test-tlb/issues/5



Submitted by the same person who is trying to troll Linus. Looks like the troll is happy with the result:

> Thank you so much, it's so much more inclusive now. My rabbi will be pleased.


Trouble is the commit is there: The thing has been taken at face value.

This galloping madness is beginning to scare the shit out of me.


No it hasn't.

>We realise it's a troll, but we had an internal discussion and we decided that we wanted to remove these anyway. We're not being terrorised into change just because a (bad) troll appeared, they just happened to bring attention to a real issue.


"We didn't do it because the troll said so, but because the troll said so".

Either way, the decision is ... whichever derogative may not yet be blacklisted, sorry, interdicted.


It has no algebraic data types and pattern matching.


Someone wrote pattern matching as a macro - nim is pretty powerful.



That's the one.


Do you have a reference for that immediately to hand, or should I search for it ...


What algebraic datatypes is Nim missing?

It has generics, tuples, tagged and untagged unions, it even has C++20 concepts.


This is enough to make me keep using C++ for the use cases where Nim is meant to shine, or choose Rust instead. If I'm to learn a modern language, I really expect it to support modern paradigms.

I can see why it'd be interesting to someone with no C/C++ knowledge to get into systems programming though.


Tabs are not allowed for indentation.


Nice. I don't mean to be flippant, but I would consider that a feature.


Preferring spaces for indent?


Being opinionated


My preference is for spaces as well. Sadly, go uses tabs.


const hand* ^^ is that a pointer? Are we moving backwards?


No, it isn't. `*` after a name means that the variable/function/type/etc. is public and can be seen/used when you import a module.

So the whole expression just means "a public constant string (automatically inferred type) named `hand`".


oh, that was a surprise. thanks


How about the garbage collector? For really performance sensitive applications you'd turn it off and resort to manual memory management?


Yes, but the GC is very flexible so you might get away with using its soft real-time features[1].

1 - https://nim-lang.org/docs/gc.html


Nim also has a stack based region allocator, but it didn't seem too well documented when I tried to use it.


You can also mix GC-managed and manually allocated types in the same codebase.


Is it the best?

I read Rust is basically a safer drop-in replacement for C.


Learning rust is difficult, and takes time. It's debatable whether it's worth it, but a learning a new paradigm (automatic memory management via borrow checking) hardly qualifies as a drop in replacement if you don't know how to use it already.


I like Nim, although I don't think it's great for everything and I do think it fills a particular niche. For me, that is a systems-programming language akin to Go or Rust with a familiar syntax. Coming primarily from Python, sometimes I need a language that is a) safe b) fast c) easily capable of producing a cross-platform executable. Nim provides all of these with a Pythonic syntax and style, and that is really the main reason I like it. It lacks the sponsorship and audience of the other two, but is still a well maintained language with an active community and all the core functionality you would likely expect. That being said, a few years ago I was a strong proponent of Nim, while today it is clear that Rust and Go have captured the mindshare and continue to grow momentum. In fact it becomes hard to recommend Nim when I think of where these 3 languages will likely be in 5 years.


I've played with it, and have written a basic fasta/fastq bioinformatics library in nim (https://github.com/jhbadger/nimbioseq)

What I find appealing is that seems to reach the goal of "a compiled typed language that feels like a scripting language" more so than other similar languages like Kotlin and Swift. There is just so little "boilerplate" code that always seems to have to be included in compiled languages and yet it seems to generate decent smallish binaries (via C). There's also a Javascript backend for web development, but I haven't used that.


I've tried it out and read the Nim book, but I'm not using it for any larger project right now. So here is a biased opinion.

Pros: Nim is about as easy to program as Python, has the same speed as C, a working FFI, and all the usual bells and whistles of modern "battery included" languages like a package manager with lots of packages. It is garbage collected, which is good -- about this, some will disagree, of course. It has nice high level constructs and doesn't attempt to reinvent OOP or something like that, the language is fairly straightforward. It also has a powerful macro programming facility, which is cumbersome to use though.

Cons: The community is too small and so far has not attracted CS people or many professionals, and there is the usual bulk of abandoned or undocumented packages you get with these kind of languages (more on that below). It has a few controversial syntax choices (e.g. identifier case rules) and also a number of semantic misfeatures that ease compatibility with C. It has support for native threads but no Green threads like Go, and consequently also no Green thread -> OS scheduling that would be ideal. (You'd like the language to do some flow and dependency analysis and parallelize to Green threads automatically, which are then mapped to OS threads, but AFAIK only few experimental languages can do that by now.) Its garbage collector is not optimal and not as performant as Go's, I believe. It uses whitespace for blocks, like Python.

Overall, Nim is a pretty good general-purpose programming language.

I should say that I have a long-term interest in esoteric languages and have been working on my own for a while. However, my main use case is desktop application development and unfortunately so far there is not a single new language that I would really recommend for developing desktop applications, unless you're fine with bindings to some monstruous web interfaces (Elektron, Sciter, etc.) and want to program half of your application in Javascript.

Rust, Go, Nim, Elixier, Julia, Crystal, etc. do not have GUI frameworks that are ready for prime-time use in production, except maybe for a few interfaces to web apps. Their native libraries (like Nimx for nim, duit for Go, Conrod for Rust) are unfinished, limited or simply too impractical, and bindings to Qt and wxWidgets are either undocumented, incomplete, or suffer from weird license restrictions (like a Go Qt binding I've taken a look at, I forgot its name). Some of the libraries also create monstrously large executables.

For command-line tools you can use any of them, just like thousands of other languages. For web programming, you can also use them but then there is also Common Lisp, Racket and plenty of other languages good for that. For desktop applications with modern GUI, on the other hand, you will be too limited with any of these languages and constantly chase some incomplete bindings or try to figure out how the bindings work. (Most docs for bindings simply assume that you've used the respective library a thousand times in C or C++, in case of which you could, frankly speaking, probably safe yourself the trouble and do it in C or C++ anyway.)

For this reason, I've decided to use Lazarus for my GUIs. Qt with C++ or Python is also a good choice. I also use Racket, but its native GUI is too limited, and still have hopes for Go.


I'm writing a Scheme interpreter in C++ with the express purpose of easily using Qt from it. It supports call/cc efficiently, which I hope will allow me to write Scheme programs handling GUI ops which use signals/slots behind the scenes in direct mode (basically have (potentially many) Scheme threads of execution instead of callbacks). Another thing that I'm vaguely interested in experimenting with is offering a "reactive"/functional/immediate mode layer on top of Qt with it, but I don't have enough experience yet to know how possible that will be.

The interpreter currently relies on refcounting for simplicity and to provide deterministic latency behaviour. It's (currently) a simple s-expression interpreter partially because (at least at first) I want to use it to interoperate with another Scheme system via sending s-expressions forth and back, and then that's the lowest latency option. I've got various ideas in the areas of debugging and typing that I'll try to implement, and if I succeed on that path and start wanting to use it as the main Scheme system then I'll certainly move on to compiling to byte code or use a JIT.

I just started a month ago, and have to nail down licensing with my employer, when that's settled I'll publish the code.


That's a very interesting project. Still, if you're aiming at real-world usage, please seriously consider postponing your own language+implementation (or keep it as a side project) and writing a library for Chez Scheme instead. That would be awesome.

Chez is very mature and probably the fastest Scheme available. It's so good that the Racket team is currently converting Racket to Chez as the backend language and compiler.


I know about Chez and Racket's effort. The reason I'm rolling my own is that as mentioned I've got ideas to help debugging and typing that I find easier to implement when knowing the system and the system is simple. And that I want to control GC pauses, and get easy interop with C++ (e.g. I can use Qt strings as Scheme strings that way). I also don't want to be tied into a particular Scheme implementation (e.g. some of the GUI apps that I write I will want to run client side in the browser, too). I would be happy to meet with any Chez users/implementors though to learn about its internals etc. I'm looking for Scheme and CL people to meet in London, BTW (https://www.meetup.com/London-Metaprogrammers/ - first meetup soon).

PS. consider it to be a Scheme really optimised for doing work with Qt. It appears that binding Qt well into another language is difficult (Python being about the only one where that was done successfully?), so I'm taking the approach of working "close to the metal" (C++), do things that are better done in C++ (like subclassing widgets) there, then making interfaces to scm as I go (i.e. make it so easy to make interfaces that this is a reasonable approach to do). That way I don't have to do all the work of binding the entirety of Qt, I can use qtcreator as I see fit, I can decide on a usage basis how to interface to a widget (modal in the Scheme view but not modal in Qt's view?, when does it need destruction in that case?). I guess the knowledge or abstractions coming out from this might be portable to other implementations, though.

Also again, I also do have code in another implementation (Gambit) that will have to stay there for the time being; communicating with the GUI via sexprs will of course be an indirection, but given that web programming could work the same way (the Scheme implementation on the server communicating with the one in the browser) it looks like the right approach to try for me. That will also mean that the approach will work with any Scheme implementation as the server (Chez, Chicken, whatever).


I am curious to know what you find limiting about the Racket GUI. There have been some interesting[1] things[2] being developed with it recently. I have been able to use it to write a stock trading simulator[3] with price charts.

[1] https://alex-hhh.github.io/2018/06/a-racket-gui-widget-to-di...

[2] https://alex-hhh.github.io/2018/05/running-and-cycling-worko...

[3] https://github.com/evdubs/chart-simulator


Same as OP but posted from another account. Well, it always depends on the application. Here are the main limitations:

1. no internal drag&drop from control to control in a frame or from frame to frame, like from an editor snip to a listbox, or from a listbox item to a text field or canvas

2. text% and editor-canvas% are too slow for some applications, esp. for displaying lots of data fast or styling snips

3. text% does not allow associating arbitrary data with ranges (strange enough, list-box% has this)

4. text% uses a nonstandard format, neither RTF, XML, HTML, rich text is not easily drag&droppable or copy&pastable to other applications in a platform-compliant way without writing your own converter

5. no images in list-boxes, and generally speaking no advanced custom "grid" control (e.g. also no editable fields in list-boxes or similar table features)

6. no images in menu items

7. no toolbar, you have to make one your own and it will not be platform-compliant (macOS)

8. no docking manager or other advanced user configuration controls (we could implement these easily if we had frame-internal drag&drop, but we don't, so we can't)

9. no built-in input validation for text fields, like limiting one to integers, floats, dates, you have to do that on your own

10. it appears that some icons are not properly installed by Racket's deployment functions even if you specify them in the #:aux argument of create-embedding-executable

11. no access to tray icon

12. no way to obtain system colors from the system color scheme for custom controls, so you cannot create theme compliant custom controls

13. clipboard operations are limited (unless this has changed since I checked last time), meaning e.g. you cannot easily implement a "receiver" for some mime type data

14. related to the previous one, only whole frames can receive drag&drop objects and you basically just get a file path

That are all the points off the top of my head. For me, only 1, 3, 4, and 5 are problematic and 1 is a show-stopper. 3 is also important, since implementing this on your own can lead to a vast range of problems (you'd have to constantly maintain a data structure in sync with the snips in the editor).


Consider posting this on the Racket mailing list. If no one asks for it, we don't know what to implement next.


I added this feedback to racket/gui. Not sure if that's helpful.

https://github.com/racket/gui/issues/115


> It uses whitespace for blocks, like Python.

Why is this a con?


It's arguably more error-prone, e.g. Rob Pike justifies Go's decision to use curly braces like so:

>Some observers objected to Go's C-like block structure with braces, preferring the use of spaces for indentation, in the style of Python or Haskell. However, we have had extensive experience tracking down build and test failures caused by cross-language builds where a Python snippet embedded in another language, for instance through a SWIG invocation, is subtly and invisibly broken by a change in the indentation of the surrounding code. Our position is therefore that, although spaces for indentation is nice for small programs, it doesn't scale well, and the bigger and more heterogeneous the code base, the more trouble it can cause. It is better to forgo convenience for safety and dependability, so Go has brace-bounded blocks.


I never understood this. Whenever I see similar criticism, I wonder: what the heck does its author use to edit programs? Notepad?

(Well, given it's Rob Pike and looking at some of his work[1], this time it may well be close to the truth... ;))

[1] http://acme.cat-v.org/


and then you do both, indents and braces, indents that it looks nice and braces to satisfy the machine. Then you can just omit the braces... If i would just got a penny for each time i've counted braces...


What Crystal is for Ruby devs, Nim is for Python devs, I guess.


In theory yes, in practice it's not that clear.

You make a fast Rails in Crystal and a large percentage of Ruby community will jump in. In Python you can't do that, the community is fragmented. And you have already Julia..


In some ways, yes. But in practice Crystal is far closer to Ruby than Nim is to Python.


I read the article, and I’ve been spending the past 20 minutes looking at the SPA framework.

I’m still not sure what it is or why anyone would use it. It looks extremely complicated and verbose.


Karax is very promising to me. The Nim forum was re-built with it recently: https://github.com/nim-lang/nimforum However, it has no totally no documentation, and seems super alpha.


Don't know why you're being downvoted. I had the same experience reading through Karax GitHub. I might be spoiled by other docs.


Karax needs a promotional website, badly. It's a really great SPA framework and IMO is totally competitive with React.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: