Show HN: “Nim in Action” is now available
nim-lang.org
nim-lang.org
My impression of Nim is that it is what Go should have been, if language developments of the past 40 years were taken into account, so if you like the simplicity of Go's syntax, but want modern features, seriously consider Nim.
I personally couldn't get over the significant whitespace, (relying on invisible characters doesn't sit well with me) [1], but apart from that I like the language a lot!
@dom96 Do you think that the focus on web development is good to have? I realise that it is what a ton of people do these days, but since web developers already have so many technologies to pick from, perhaps selling the book as aimed more at system/game even native desktop developers could spring up more interest.
Also, how exactly is the garbage collector tied to the standard library and the language itself? For example, if I opt out of the GC completely, would I end up in a situation similar to D, where I'm not using GC but everything around me still is, so I have to carefully program around it, or is it handled differently? (And can you possibly compare Nim and D as the languages seem to be covering similar territory.)
Lastly, what major work still needs to be done before we see a 1.0 release and how best can we help Nim to move towards that goal right now?
Thanks, back to the book now...
1 - Maybe a gofmt style tool would help somewhat.
Personally I love significant whitespace and have started using Nim because of this feature, basically back in the day I just wanted a Python alternative that was compiled. If you really dislike it that much, you may be able to convince Araq to bring back his old time idea of allowing different syntaxes in Nim. As for a gofmt tool: `nim pretty` exists but may need to mature a bit.
I believe that a focus on web development is good. One of the reasons why the book has such a strong focus on it is because I have spent most of my time implementing stuff which is necessary for web dev in Nim, and I want to show it off. The fact that I have a lot of experience with it helps too.
I would love to show off as many things as I can, and I might look into including some examples of SDL, SFML, and more as well as ways to utilise Nim's real-time GC for games. But I must be careful, the book is already becoming rather large :)
As for systems, there is a whole chapter dedicated to Direct Hardware Control in the book. But I will make a note of maybe including something for native desktop developers.
In terms of the GC, I don't have as much experience using Nim with no GC as I would like. So I can't really comment as to the current situation.
In terms of a comparison to D, I've already received feedback to add D to the language comparison table in Chapter 1. To compare these properly I will need to do some research first.
Nim is very close to 1.0 now. We are planning on looking at the standard library and ensuring that it is in tip top shape before 1.0 is finally released. There is also work currently happening to make asynchronous IO multithreaded.
Thanks for the feedback and hope this answers your questions!
I don't think it is possibly to cleanly implement a epoll/kqueue-backed multi-threaded (web)server/reactor without it.
Currently you have to use allocShared, allocShared0 etc to use shared memory. You must then manage the memory yourself.
I certainly understand the appeal of whitespace if you're coming from Python or Haskell etc. just wanted to point out that it might not be for everybody.
As for the web development focus, I would certainly understand not wanting to discuss topics in the book that you yourself are not that confident about.
Good luck with Nim going forward.
I will likely give Nim a go, despite its significant whitespace and weird variable naming rules. In any case I continue to follow Nim and wish the project every success.
Pretty much how, parens are not a concern for actual lisp programmers.
Please do try it out and report the results on the Nim forums (or via blog post). This is one of the chapters where I will need to do some research first, as I don't have much experience with this kind of stuff. So any ideas for this chapter are very much appreciated!
I thought it would be a nice chapter to end the book with though. Plus I am excited to play with this sort of stuff.
My current plan for this chapter is to try replicating some of the projects in the Arduino starter kit and to see where I can go from there.
I am not sure if this is covered, but did not notice it mentioned in the contents.
Thank you for your feedback!
The biggest dimensions for me when first evaluating a new language that I might want to learn more about someday are typing (dynamic, untyped, or static, and if static whether that's of the Haskell variety or more mildly anti-certain-class-of-errors-driven plus performance-driven like most other things) and garbage collection (none, forced, or optional). That info helps me immediately bucket what sorts of applications this new language could help me take on in a better way than other languages I know. With Rust, watching it develop I didn't think too highly of their decision to remove the @ sigil (that is, remove the GC from the core language). That's what ultimately made me think of Rust only as something I'll ever try to learn and use if I come across the narrow (in my interests) problem domain of "I absolutely require a Safe program but for some reason I can't use a GC language."
I think your first 12 pages do a pretty good job at highlighting some of the hooks that originally put Nimrod on my watch list whenever ago, though personally I'd put the style insensitivity thing last (and it doesn't cover things like omitting parens for single-arg or no-arg functions but you mix that particular style choice around throughout the chapter). Those hooks, including some you don't really cover yet, are speed (like, at or even sometimes beating C-level speed), all three of optional, tunable, implementation-detail-swappable garbage collector with access to malloc/free or even just embedding C code directly like you might embed ASM code directly in C code, inferred static typing to minimize ceremony, the huge list of pragmas to tell the compiler -- which humbly admits it tries its best but is not all-knowing -- about useful things for performance or other reasons, user-defined compiler demands (not "hints", as it's not optional) to make optimizations via term-rewriting macros, style choices (but sadly no Lisp-like dashes in function names), and an awareness of and support for many higher level language features enjoyed by other languages. No forced main() and whitespace indentation make it immediately comparable to Python on the surface which is a nice bonus (for those that like Python anyway). Taking all these things together, there isn't really a comparable language, or at least not one that's on very many people's radar. I think the only language worth mentioning (or not, per strategy) as one that might surprisingly come up from behind in n years and eat Nim's potential big lunch by then is Pony.
Another nitpick, in the section on functional programming, why use var instead of let? The immutability story is just as important as first class functions... And you're missing the item (->) in the list of things the modules were imported for...
I agree with many of your points and I will do my best to incorporate them into my book.
The reason I have compared Nim to Python so heavily is for two reasons:
1) I used to be a Python programmer and chose Nim as a replacement.
2) I see a lot of Python programmer's trying out Go and saying describing it as a "better, faster Python". Perhaps that is just a HN illusion. I in turn believe that Nim is far closer to Python than Go will ever be. I am trying to show people that. Perhaps I should be comparing Nim to Go more as well.
Your list of hooks is brilliant. It's hard for someone like me to remember features which make Nim unique since I use it almost every day, so these are really useful. I will see about mentioning some more of those things, in order to hopefully grab more people's attention!
I have heard of Pony but have not had a chance to try it out. Looks promising.
> Another nitpick, in the section on functional programming, why use var instead of let? The immutability story is just as important as first class functions... And you're missing the item (->) in the list of things the modules were imported for...
Will fix, thank you! I have started out using 'var' then changed everything to 'let' (where appropriate), must have missed that one.
Thanks again!
C was my first language, so I had the "significant white space" prejudice. The first time I tried it, I was hooked - because I hate code improperly indented.
Yes, you can go the gofmt route in order to eliminate indentation wars, but I love languages where the syntax enforce it: it is a very pragmatic design (no need for explicit start/end of blocks, no ";" to mark the end of the statement).
Strange enough, Nim enforces indentation but is very liberal with case sensitivity. Go figure... :-)
EDIT: s/sensitivity/insensitivity/
Do you mean "case insensivity"? AFAIK dynamic languages where you can do that are very much case-sensitive, Python and Ruby certainly are.
I agree, but my concern is not correctness, it is aesthetics.
Why? Reading a computer program is often harder than writing it from scratch, so I like when languages enforce (or at least encourage) a name convention - just to keep it easier to read. Does Nim have something like PEP-8?
https://github.com/nim-lang/Nim/wiki/Style-Guide-for-Nim-Cod...
It doesn't matter for my own code because I already write it that way, but it enforces good indenting behavior on others who might otherwise forgo it.
Most editors can be configured to show whitespace. Either in a low contrast color to avoid creating too much noise, or toggled in/out when needed.
> how best can we help Nim to move towards that goal right now?
There are many ways. One way of course is to use Nim, test it, give us feedback, write Nim libraries and tell other people about it. But the best way is to get directly involved in Nim's development on Github, help us fix bugs, discuss the future direction of the language and help us implement new features. Here is a list of "Easy" bugs to get you started: https://github.com/nim-lang/Nim/labels/Easy
Another alternative is donations. Nim accepts donations through Bountysource[1], and Gratipay[2].
Better standard library support for Go-style CSP. Given that CSP is one of Go's biggest selling points, it'd be great if people could easily translate concurrent Go programs to Nim and see the benefits. Right now the lack of a "select" statement makes that quite hard, especially for a beginner.
Even if you don't intend to purchase the book I would love to hear feedback from you about the first chapter (which is free!)[1]. Really excited about this book and am looking forward to any feedback at all from the HN community.
1 - https://manning-content.s3.amazonaws.com/download/6/df42fc6-...
One small note, since I know that this book is getting started: Rust does have some amount of CTFE available in nightly (const fn), and it and/or compiler plugins may very well be stable by the time this book is released. So you might want to make a note to double-check the state of that when you're closer to a final draft.
Congrats and good luck! Writing a book is so rewarding, but so draining.
I will certainly keep my eye on that and update my table appropriately :)
Even though I write Nim code, I still bought the book, but more so for the later chapters:
8. INTERFACING WITH OTHER LANGUAGES
9. METAPROGRAMMING
10. DIRECT HARDWARE CONTROL
Since I don't have very much experience there. Also maybe a chapter on debugging might help, especially for people that are coming from Python or Ruby.Best of luck with the rest of the writing!
I think you're right, Nim compile times are fast and deserve to be mentioned. Will make a note to add this.
Debugging will be a part of Chapter 5. But I will make a note about addressing people coming from Python and Ruby.
Thanks again!
this will encourage students and casuals to look into nim
Does anyone with significant Nim experience care to lend some opinions? I don't want to start a flame war--I'm genuinely curious.
I assume the distinction you are making about "serious" is around manual memory management and the GC?
In which case, I think you are probably right in your bias. That said and while i have no experience with it, Nim claims to have a real-time GC mechanism builtin. That is they support a max pause time parameter. There have been other real-time GC systems out there before and they tend to work well for other definitions of "serious".
Are there any other good references for what the current state of these sorts of capabilities have reached? There are any number of crates out there for this sort of thing, but assessing usefulness seems dodgy at this point.
https://github.com/teepee/arewewebyet looks abandoned.
HTTP Server? DB Drivers? Frameworks? E-Mail?
I mean on Node.js I use Hapi (+a few plugins) and Sequelize, which does pretty much everything for me. I would guess, that everything besides the DB drivers is available in Rust too...
For servers, there's rotor and hyper. Database drivers, we have very good Postgres and MongoDB options, with some SQlite bindings too. Possibly others, I don't pay too much attention to this space. We have multiple ORMs, one of which is being written by the maintainer of Rails' ActiveRecord. As for frameworks, we don't have a ton of full-stack ones, but a number of the smaller ones, iron, nickel, etc. I haven't explored email yet, but I know that there's some work there.
Frameworks - all is fine
HTTP client - Hyper works fine.
Email - homemade email servers is a good way to go into blacklists, so mandrill/postman is the much better choice.
"Several hundred thousand things about the place" - not actual anymore, there are rare things which are not covered by crates. Just open crates.io and type name of thing you need.
edit: It seems that I can't edit that comment anymore.
So... why not using it to replace C and C++? Since I have worked with Nim (and I use it to implement my own language) I would say "hell yes"! It is such an immensely better language and it integrates perfectly with those eco systems. The GC is a good one (or well, there are 5 to choose from) and it is for many, many applications not an issue.
And before pcwalton drops in with his endless spamming about Nim not being safe, Nim being undefined etc etc (it's getting quite annoying), please spare us this time.
> And before pcwalton drops in with his endless spamming
about Nim not being safe, Nim being undefined
Well, it is, isn't it? Is he wrong about Nim not being safe when not using Boehm GC? Does it not segfault when sending GC pointers between threads?He only jumps in, when someone claims Nim is safe or the sweet spot, or something equally wrong. Nim's pretty syntax comes with a price, just like Rust's safety comes with a different kind of price.
Personally I am quite sick and tired of that particular "take" on Nim - why not for once criticize other parts of the language? :)
Because I'm not interested in criticizing languages as a whole—that would be language warring for no reason. Claims of memory safety are what are important to me, just as, for example, claims of correct crypto constructions are important to crypto people.
Anyway, I see no reason to go further here, given that nobody has claimed anything is memory safe.
Claims that Nim is memory-safe when it's not is not a difference of design goal though.
It seems to me that a) Nim is (or at least is meant to be, but bugs can sidestep it) memory safe if you stay within the rules for it, and b) Nim is not throwing around vague claims of safety that are not documented in the language manual.
That's completely worthless. C is also memory-safe if you stay within the rules for memory safety.
> Nim is not throwing around vague claims of safety that are not documented in the language manual.
Of course not since nim is not posting on HN (as it's not a sentient being prone to procrastination) it's obviously nim supporters making claims about nim's safety.
It's really not any weaker of a guarantee than Rust makes, being memory-safe if you stay within the rules of not saying `unsafe`. Or opening /proc/self/mem for writing, anyway.
I'd also feel a lot better about Rust's moral highground of memory safety if its undefined behavior was actually spelled out a bit more rather than just punting the hard parts to llvm docs. I don't think every Rust user knows how to avoid aliasing problems between `&mut` and `*mut` either.
That said, I don't agree with the claim that Nim is less safe than Rust because Nim uses "ptr" types and Rust uses "unsafe" blocks to mark unsafe regions. I prefer Rust's approach, but it's pretty much just a question of UI, not anything substantive.
As I understand things, though, solving them is a work in progress.
And you asked why this happens, and I answered, because Nim claims it is secure. Not more not less.
It's like saying OpenSSL is perfectly (or as good as it gets) secure, and there aren't any known vulnerabilities. That statement is going to get a strong reaction from anyone that specializes in security and reads HN (for example tpatcek).
I don't like or dislike Nim. I did like Nim's macro system, although I fear its too powerful (it seems like macros would be really easy solution in many cases).
But I am genuinely interested in where this claim is made, perhaps we need to adjust some documentation or make things more clear - so do point us to it if you find it again.
If he has said that, yes, then that would be wrong [1, 2] in that you cannot send GCed references between threads in the first place. For example, the following code results in an error:
var s = "foo"
proc foo {.thread.} =
echo s
createThread(foo)
Compiling this results in: test.nim(3, 6) Error: 'foo' is not GC-safe as it accesses 's' which is a global using GC'ed memory
The problem here is one of expressiveness in that it is difficult for threads to share data (outside the limited and still experimental `parallel` construct). I've proposed a mechanism (shared, individually lockable heaps) modeled after Eiffel's SCOOP approach to remedy this, but so far this is just a proposal.[1] Modulo any remaining compiler bugs, of course, or using explicitly unsafe features.
[2] Also, are you maybe confusing this with Go, which does have such a problem?
[1] It may have been that using global variables to share refs between threads did only trigger a warning at some point, not an error. I'm not 100% sure about that. But the serialization has been there since the early days of multi-threading support in 2011.
But how could the segfaults then happen? Aha, you mean the test code perhaps shared via globals?
However, that he stopped in his own comment to bring it up and drop a counter says more about him than pcwalton. Shows a strong bias for and protectiveness of Nim while also disregarding the entire reliability or security aspects of the language. That's really something for a C++ alternative given its safety focus. ;)
(Nothing against Nim, I haven't worked with it yet)
I strongly prefer Rust's safety but it's not quite the same as a blind FFI like Nim.
Can you elaborate on to how not having to type unsafe makes debugging of this easier?
But I stand corrected.
Historical accident: they started surfacing around the same time, Go was originally described as a systems language (which it never was according to the usual meaning of the term) and Rust had more application-level features (built-in "GC pointer", green threads). As incorrect as it was, the initial… impression? — it's probably the wrong term but I don't have a better one — remained.
Probably doesn't help that Rust also has a number of features Go is criticised for lacking (generics, non-nullable references, immutability support, …)
Fun fact! Go has roots in the Limbo[0] programming language, which runs in a VM, is garbage collected, has communication channels, and was used to write the Inferno[1] operating system, which is sort of a successor to Plan 9 (which is itself sort of a successor to Unix).
[0] https://en.wikipedia.org/wiki/Limbo_programming_language
[1] http://www.vitanuova.com/inferno/ https://en.wikipedia.org/wiki/Inferno_%28operating_system%29 http://c2.com/cgi/wiki?InfernoOs
Does Nim have a good answer to this?
It's not perfect, but for my uses it has been alright (but then I'm ususally the kind of person who prefers to use debug printing and just studying the code)
Nim also shows very nice stack traces on uncaught exceptions so that also reduces the need to fire up GDB.
To get to a point where we have something good to use, though, there are a few libraries to develop. I started working out a basic layer for linear algebra, that is needed in many applications - see http://unicredit.github.io/linear-algebra/
I hoped I would be able to start working on some neural network stuff based on that, but I did not find the time yet...
>Nim allows you to use snake_case even if the identifier has been defined using camelCase, and vice versa.
Can you also just write it all lowercase, and same synonym effect? i.e. snakecase
> The default garbage collector is real-time so it allows you to specify the amount of time it should spend on collecting memory.
Since Nim compiles to C, which is not garbage collected, does Nim just automatically add its own C-based GC library behind the scenes (no small task), or is it actually just adding calls to free for you?
> This applies to languages such as C++, Pascal and Ada. But these languages still require platform specific code when dealing with more specialised features of the operating system, such as creating new threads ...
Not true any more for C++, since the new C++ standard 5 years ago, which contains cross-platform standard library tools for multithreading.
>The speed of a programming language is one characteristic that is often used to compare multiple programming languages
Since this statement is in the book, it would be nice to see Nim programs participating in the online benchmarks game.
>Table 1.2 Common programming language features
A little misleading or perhaps just incorrect to place a No in C++'s box for metaprogramming. Entire books have been written on C++ metaprogramming.
> Can you also just write it all lowercase, and same synonym effect? i.e. snakecase
Yes, the first character is case sensitive, but the rest is not. foobar == fooBar == foo_bar == foo_Bar but FooBar != fooBar.
> Since Nim compiles to C, which is not garbage collected, does Nim just automatically add its own C-based GC library behind the scenes (no small task), or is it actually just adding calls to free for you?
Nim adds its own Nim-based GC library behind the scenes. In fact, it supports multiple GCs (which can be changed via the --gc flag).
> Not true any more for C++, since the new C++ standard 5 years ago, which contains cross-platform standard library tools for multithreading.
Is this standard well supported by now? I'll change it to 'C' in any case.
> Since this statement is in the book, it would be nice to see Nim programs participating in the online benchmarks game.
I agree, maybe you can convince them to include it: http://benchmarksgame.alioth.debian.org/play.html#languagex :)
> A little misleading or perhaps just incorrect to place a No in C++'s box for metaprogramming. Entire books have been written on C++ metaprogramming.
Somebody else raised this point. Will correct.
Hope this helps!
>Is this standard well supported by now? I'll change it to 'C' in any case.
The standard is 5 years old this year and nearly every major compiler has supported it for years, and the big ones supported it before the standard was officially in place. So changing it to C would be much more accurate.
That's not to say that each platform's unique tools, i.e. Apple's own GCD for multithreading, are not still available and widely-used. But C++ lets you not worry about platform-specific multithreading any more, and it's quite nice! In addition to multithreading primitives in the standard, there are also higher-level task-based tools like futures and promises that are cross-platform also.
I will be spending some time reading about this, since it's definitely the most disruptive aspect to Nim, considering that GC in a systems language is not a "solved problem" in general. Coming from C and C++ I'd most need to know exactly how the GC was working to be comfortable with the idea.
There are also many others: https://www.google.co.uk/search?q=garbage+collector+gc+site:...
Also, feel free to ask questions about the GC in the Nim forum or on IRC. That way other Nim developers can chip in and offer better answers than I ever could :)
The book is not available yet, only the first three chapters.