Nim is a language I really want to like. Having looked for a language that's 1) Cross-platform, 2) Script-like syntax and 3) C Speeds, Nim should be my ideal language. What I find though is a sense of frustration that grows over time when using it. Sometimes this stems from the quality of the documentation and other times from obscure problems that's hard to Google and get an answer for.
I do appreciate Nim, and bought Dom's book, but I feel it's missing a trick in its current state. No doubt I'll try it again as I'm ever the optimist :-)
Nim is such an odd combination of "amazing" and "huh, that's just weird".
There's a powerful theme — C-like performance with an expressive syntax and automatic memory management — that's undercut by a range of somewhat scatterbrained, idiosynchratic features.
Nim's feature set is ambitious, and it really feels like Nim's authors decided to go "breadth first" rather than "depth first", implementing everything but the kitchen without considering that some more complicated ideas could be deferred until the core language was mature; Nim would have benefited from a more conservative, agile, minimalist approach. At least it would have allowed it to reach 1.0 and more widespread adoption earlier.
Nim also makes some design choices (first-class iterators, the case insensitivity madness, the massive amount of pragmas, OO inheritance, out arguments, etc.) that I wish would have been left on the drawing board to mature.
A casual skim through the top of the commit history indicates that Araq (Andreas Rumpf) is still doing almost all of the development. That's a red flag — being responsible for a complex language, compiler, standard library and documentation is a lot of work. (And it's of course a dangerous bus factor.)
I also think it's a mistake to charge for a book at such an early stage when the quality of the official documentation is less than stellar. dom96 is Nim's most active evangelist on HN; if he wants Nim's adoption to take off, making the book available for free should, strategically, be a no-brainer.
That said, it's not all negative. If evaluated purely on technical merits, Nim is one of the most promising languages currently in development, and it's one of the languages I intend to use this year for various smaller, experimental projects.
> I also think it's a mistake to charge for a book at such an early stage when the quality of the official documentation is less than stellar. dom96 is Nim's most active evangelist on HN; if he wants Nim's adoption to take off, making the book available for free should, strategically, be a no-brainer.
Sadly I cannot do that, or at least not in the near future. My publisher holds the copyright, so unless I get explicit permission to offer the book for free this cannot happen.
Perhaps in hindsight it would have been better for me to write this book independently. But if that were the case I likely wouldn't have the motivation to get it finished.
Nim is really cool. I tried it out for a few weeks last year.
It's biggest problem is the lack of engaged contributers (really only 2 or 3), leading to many bugs ( you can never really trust the compiler), little documentation, and a very messy standard library.
Creating a language is really hard work. Nim is impressive considering how many people work in it.
But in it's current state you can really only use it for "just for fun" projects.
I've been put off it for similar reasons - there doesn't seem to be much community or momentum. This means on the one hand that there's not as many resources as you might need and on the other hand that I'm concerned the project might falter and become abandoned. By contrast I'm really interested in Rust because as well as having interesting features I feel pretty confident that it's going to keep growing thanks to it's enthusiastic community.
The sad thing about it is for many situations, Nim would be a better fit than Rust just due to GC (this makes Nim conceptually simpler and higher-level in a lot of contexts). Yet they can't raise more than $3k in support (see the top of this link).
Not sure what has to happen for adoption but it's a real gem of a language that just needs users.
> Yet they can't raise more than $3k in support (see the top of this link).
Unfortunately the image on that page is misleading. We have been getting ~$1300 every month for the duration of our BountySource campaign, which isn't bad. I think that the ~$3k value only includes direct non-recurring payments via BountySource.
Sadly, it isn't enough for either of us to work full-time on Nim.
Nim's idea is great, but the implementation and doc aren't currently at a place where someone like me that isn't ac advanced programmer could efficiently utilize. I read the opening chapter last year though and it is really well written and clear. I'd really like to see Crystal, Nim, or Red take off.
A language is as good as its libraries are. Do you provide libs for IOT? WebDev? games? People say, Go is successful because it's backed by Google, no, it's successful because its std lib has a socket and an http server. Focus on a niche, be successful in that niche and people will try to use it for everything else.
Nim's standard lib also has sockets and http. Nim's niche is clean and fast code, with strong C/C++ interop and metaprogramming.
Run 'nimble search game' to get a list like this (I did not copy and paste the whole list):
libtcod-nim:
url: git://github.com/Vladar4/libtcod-nim/ (git)
tags: roguelike, game, library, engine, sdl, opengl, glsl
description: Wrapper of the libtcod library for the Nim language.
license: zlib
website: https://github.com/Vladar4/libtcod-nim
nimgame:
url: git://github.com/Vladar4/nimgame/ (git)
tags: game, engine, sdl
description: Simple 2D game engine for Nim language.
license: MIT
website: https://github.com/Vladar4/nimgame
sfml:
url: git://github.com/fowlmouth/nimrod-sfml/ (git)
tags: game, library, opengl
description: High level OpenGL-based Game Library
license: MIT
website: https://github.com/fowlmouth/nimrod-sfml
enet:
url: git://github.com/fowlmouth/nimrod-enet/ (git)
tags: game, networking, udp
description: Wrapper for ENet UDP networking library
license: MIT
website: https://github.com/fowlmouth/nimrod-enet
fowltek:
url: git://github.com/fowlmouth/nimlibs/ (git)
tags: game, opengl, wrappers, library, assorted
description: A collection of reusable modules and wrappers.
license: MIT
website: https://github.com/fowlmouth/nimlibs
nimrod-glfw:
url: git://github.com/rafaelvasco/nimrod-glfw/ (git)
tags: library, glfw, opengl, windowing, game
description: Nim bindings for GLFW library.
license: MIT
website: https://github.com/rafaelvasco/nimrod-glfw
chipmunk:
url: git://github.com/fowlmouth/nimrod-chipmunk/ (git)
tags: library, physics, game
description: Bindings for Chipmunk2D 6.x physics library (for backwards compatibility)
license: MIT
website: https://github.com/fowlmouth/nimrod-chipmunk
chipmunk6:
url: git://github.com/fowlmouth/nimrod-chipmunk/ (git)
tags: library, physics, game
description: Bindings for Chipmunk2D 6.x physics library
license: MIT
website: https://github.com/fowlmouth/nimrod-chipmunk
nim-glfw:
url: git://github.com/EXetoC/nim-glfw/ (git)
tags: library, glfw, opengl, windowing, game
description: A high-level GLFW 3 wrapper
license: MIT
website: https://github.com/EXetoC/nim-glfw
Yeah, especially for things like gamedev. It's got the perfect mix of productivity and speed, yet allows complex metaprogramming and compile time evaluation.
It does need more users, for sure, but I think it's a testament to the productivity of the language that people have done so much cool stuff already. Random example, metaprogramming & unit tests for glsl: https://github.com/yglukhov/nimsl
Agreed. I come from a python background, so Nim is more natural to me, but a lot of Rubyists (particularly those who don't do a lot of metaprogramming (my probably not accurate understanding is Ruby would probably be better here, please correct me)) are very excited to be able to wire what is essentially Ruby code that runs at near C speeds.
That's interesting, I've had the opposite experience; the few times I think I'm hitting a compiler bug it turns out the compiler is telling what I'm doing wrong but I'm misinterpreting what it's saying. Not saying this applies to you though. Was this with recent versions?
Having said that, with templates and macros I very rarely get a c compilation error (ie; an actual bug), but these are usually because I'm accidentally doing something silly like recursing compile time generation. The compiler should catch these, and it's only rare cases it doesn't.
In my experience writing a game engine in opengl the language has been rock solid and very fast. For me, the core language has been absolutely fantastic and very reliable.
Ah, it's moved on quite a bit since then. I started using it around then too, but these days compiler errors are very rare indeed, in my experience anyway.
Put it this way, the only compiler bugs I've had in the last year or so have been c gen errors, maybe two in the past year of pretty heavy use. All of those have been because I've been doing something silly with templates.
>>> Sometimes this stems from the quality of the documentation..
>>> I do appreciate Nim, and bought Dom's book...
I've said similar elsewhere.
The existing documentation isn't welcoming to those new to Nim. I've read the freebie first chapter of Dom's book and it seemed very promising and I wanted to read more. However $40 for an ebook is ridiculous. I can't afford to make that kind of outlay just to see whether or not an obscure language with very little traction is worth pursuing.
I think the best solution would be for the Nim foundation to use some of that bug bounty money to buy the rights to make Dom's book freely available on The official site.
Looking at this month's bounty goal only at $2500, I don't think they are raising enough money to justify closing off a revenue stream. I don't have experience in the OSS space but I've seen similar complaints in app development. People expect a $10 app to be $1 or less but don't realize that the $ being brought in doesn't even break even for development costs.
This is my impression as well. I'd happily replace Python with it for everything if not for the library issue.
It's hard to really trust it, though, when you've got a few semi maintained and used libraries for any given domain. It's not just the lack of libraries that's frustrating (wrapping C isn't hard), but like you said, there's a point where there's too few uers to find obscure things on Google.
Why not replace it with Julia, which should be a bit further when it comes to libraries, and can run Python? I admit, Julia is also still unstable, but it makes fast progress and should reach a stable state in 2017.
I'm not convinced of that. It's supposed to be a general purpose numerical language, and doesn't even have a decent native plotting library (gadfly doesn't seem to be maintained and using matplotlib is a hack)...tldr; it has a long way to go.
Might want to check out Plots.jl [1], which is pretty quickly becoming the de facto plotting library for many Julia users. It abstracts over various plotting backends, including native Julia graphics libraries like GLVisualize.jl [2] (which IMO has amazing potential for simulation visualizations once native graphics programming in Julia matures).
I hear the normal PyPlot/GR wrappers are pretty useful as well. They're ultimately not native Julia code, but since Julia makes it so easy to reuse tools in other languages, why not take advantage of that feature?
In my (admittedly very poor) testing, Nim can get to within 5% or so of C speeds for simple benchmarks-it compiles to pretty decently optimized C, and then can use LLVM/Clang as a backend to take advantage of all the amazing optimization work being done there, so in the end you have code that is very similarly performant to C.
I have love-hate relationship with Nim. It's the best C alternative I can find for our high performance supercomputing needs, yet it breaks my code [0] (yes, it's broken with 0.16.0 now) every single new release for the past year.
Sorry about that. Have the changes which break your code been documented in the changelog? If not please report them[0], if this is a regression then it should be fixed quickly.
It's a problem with macro heavy code in Nim currently. Macros on typed NimNode still touch too many undocumented/unspecified Nim internals, that it always takes me some time to actually figure out what is the culprit.
On the other hand, code without much typed macro transformations is really solid now, c.f. [0], the repo you are watching.
I see. I would guess that macros on typed NimNodes are indeed unstable and underused :\
Please don't give up on us. I see that you've already created a couple of issues, if we forget about them then please keep pinging us on GitHub or IRC.
I've been doing as much Nim as I can recently and really enjoying it. I just took a week to put together a proof of concept Python module wrapper around Nim code and I'm really looking forward to implementing some optimized inner loops for our main Python application at work.
I really like Nim, it is fantastic creation. That said, I didn't use it nearly as much as I would like and people complaining about bugs are probably right. Thank you contributors for your work.
If it could carve a small use case for itself, it would help it's momentum. Something to be recognized for.
Nim comes very close to be the perfect language for me (game development, machine learning etc.). Some things I experimented with including some links to show what I tried as follows:
- Fully controllable and plugable GC:
I can decide for myself when the GC runs and for how long. Very important for games. If I do not like the GC I can even write my own or choose one of the many existing ones. See: http://forum.nim-lang.org/t/2646
- Meta-programming, templates, concepts etc.:
To be able to write a machine learning library I needed something that can replace simple code (DSL) with more complex code using scalar math, SIMD, SPIR-V, OpenCL or Cuda. I also wanted to be able to automatically generate bindings for scripting. See: http://forum.nim-lang.org/t/2654 and http://forum.nim-lang.org/t/2635 .
As I understood by reading the forums they will soon merge in many concept improvements. See: http://forum.nim-lang.org/t/2396
- Nim itself can be used as an embedded scripting language:
Nim as a scripting language is used by the compiler to run Nim while compiling to generate new code. Nim as a scripting language can also be used as a more advanced configuration language (like Lua in the beginning). It can be used as an embedded or standalone scripting language as well. See: http://forum.nim-lang.org/t/2647 and https://github.com/komerdoor/nim-embedded-nimscript
- Compiling to C89 code (useful for creating libraries and cross-platform support etc.):
I want my games to compile on platforms not supported by GCC or Clang/LLVM (actually I am sure they can support them all after some patching) but with their own C89 compiler. After compiling to C it is easier for me to see what the code will actually do. Still if I really want to I can choose to compile to Javascript, C++, Objective-C and LLVM (not officially included yet) as well. See: https://github.com/arnetheduck/nlvm
- Pretty good functional programming support (as far as compiled code allows for):
For this I created a library that use the zero-overhead iterators. There are many alternatives as well and I like to be able to choose between multiple implementations of higher level functionality. See: https://gist.github.com/komerdoor/70d9c25820952624cf797890a1... .
Of course a better implementation is possible by combining this with concepts, generic dynamic method binding and all other of Nim's features. See the following again: http://forum.nim-lang.org/t/2654
- Easy integration of existing C code:
I wrote part of my code in C (low-level) and another part in Nim (mid-level).
Some things which may get new Nim users in shock but I learned to love:
- Use of indentation using spaces for grouping like Python:
I never really liked this but I cannot ignore that this made my code easier to read and discourages my preference for one-liners (yes I know bad habit and does not work well inside editors and with source-control).
- Multiple ways to write the same identifier (case/underscore insensitive):
Liked this from the beginning. I am really consistent to choose a single style but all my C code is written using underscore (ex.: typens_do_something(x)) while in Nim in prefer to use camel case (ex.: typensDoSomething(x)) or fully drop the namespace entirely (ex.: doSomething(x) or x.doSomething()).
- Multiple ways to call methods:
Both "abc".toUpper() and toUpper("abc") are the same. There are no namespace conflicts because Nim uses the best match for toUpper like: func toUpper(c: char): char or toUpper(s: string): string. It also makes it easier to add new methods for existing types while still being able to call the methods like if OOP is being used.
- Minimal support for OOP but encouraging composition over inheritance
Sorry people for the missing punctuation marks and paragraphs. It looks like there is a bug in Hackers News that does not allow me to edit my post. Tried different browsers even. Update: It seems I am able to edit this one
I don't want to be that guy but I don't see this language as usable. Not because of technical reasons but because... I mean... look at it. I can't understand what's going on. It's way too complicated.
What the hell does that mean?How the hell do I check this is correct at a glance?
I know "it's easy", "you'll get used to it", "after you learn the syntax it'll be great" but I mean... no one is going to buy that.
I get that it's supposed to be condenced but I don't necassarily buy that as being the end-all-be-all of language construction. I think that's actually quite harmful to programmers. If a single character means the same as 10 lines of a simpler language then you're more likely to hide a mistake in your code.
I'm not saying it's wrong either, I'm just saying a majority of programmers will be afraid of it. I rather like what swift is trying to do with condensing well-known operations but I don't think Nim and many other ML-inspired languages do it in an approchable way.
It took me a moment to parse, but that snippet is actually pretty straight-forward when you know that Nim compiles down to C (or C++).
type Vector* {.importcpp: "std::vector", header: "<vector>".}[T] = object
This obviously creates a type "Vector" whose underlying implementation is C++'s "std::vector". (I don't know how writeable it is, but it is* readable.)
template `[]=`*[T](v: var Vector[T], key: int, val: T)
Function declaration syntax for operator overloads is hard to make readable (as in: familiar). In fact, this is about as readable as it can get (although I'm confused by the "*[T]").
= {.emit: [v, "[", key, "] = ", val, ";"].}
As I said, when you know that the compiler generates C code, this makes a lot of sense. It's a compiler instruction to compose a string of C code.
To supplement the other response, [T] declares a generic type, so [T] is a public method with the generic type T. I'd agree though that the is initially hard to parse, especially when taking C and C++ into account, where * means something entirely different.
Well, the example you are looking at is very complex, but also you are very unlikely to run into it early! For better examples, look at the homepage: you will see something much more approachable.
The reason this snippet is complex is that:
1. It deals with the Foreign Function Interface
2. It deals with the FFI with respect to C++, which is much more complex than the one towards C, essentially because C++ itself is complex
3. It uses a particular construct (emit) that is only needed when the standard FFI is not enough
So the example is really a showcase of a particularly complex case that you will likely not encounter, unless you start wrapping C++ libraries (which is not an easy task, unlike the C ones)
To be fair, this is library FFI code so this is actually for interfacing with C++ rather than 'native' Nim. Probably not something you'd encounter unless you're making a library wrapper.
And if you are doing that, worth mentioning too that Nim has a utility c2nim that automatically translates headers for FFI access.
The first line imports the C++ std::vector type and allows you to use it in Nim. To me that seems pretty good as a one liner to import a complex type from another language.
The second line is using a template to wrap the FFI call so you can use indexing operations and generic variables with the vector.
The `[]=` is describing how to write to std::vector in nim using indexing, eg; "myVec[5]=123"
That example is complicated because it interfaces with C++ and defines a macro. Most Nim code looks nothing like that.
> I don't think Nim and many other ML-inspired languages
I don't think Nim is particularly ML-inspired. Nim's main point of influence is Turbo Pascal/Delphi and their deratives, which used to be obvious from all the "T" prefixes (TObject and so on, now largely or entirely gone from the language). Nim has things like ranges and enums, both of which come directly from Pascal.
There's also a lot of Modula-3 in Nim, too. Which makes sense: Modula-3 is also a Pascal derivative, and there's a lot of Modula-3 in Python, which Nim borrows syntax from, too.
Off the top of my head, the equivalency of "foo.bar(baz)" and "bar(foo, baz)" was inspired by Modula-3's object model, though Nim extends it to everything and not just classes. Also, Wikipedia tells me the pointer system comes from Modula-3.
Nim's official FAQ also lists Modula-3 as the single biggest influence; I have a feeling that a lot of the Wirth-isms in Nim were borrowed from Modula-3 rather than from Pascal, even if they appeared in both languages.
> I didn't know that Python was influenced by Modula. Any examples? Keyword arguments is the only that comes up on Google.
Off the top of my head:
- The module system. The syntax of "import foo" and "from foo import bar" were borrowed from Modula-3 verbatim, and Guido got the idea to give Python a module system in the first place because Modula-3 convinced him modules were the future.
- The exception system. A lot of people don't notice the exception system because pretty much every language in the '90s also borrowed that from Modula-3 (the try-catch paradigm was invented by Modula-3), but Python hews even closer to the Modula-3 model by using the word "except" instead of "catch" and allowing for multiple except blocks attached to a single try block.
- The object system is a hybrid of Modula-3 and C++; the whole idea of passing "self" as the first parameter to a method instead of having an implicit "this" was a Modula-3 thing. The official Python documentation still references it: https://docs.python.org/3/tutorial/classes.html
Guido also talks about the Modula-3 influence in a few places:
Hm, is this official, or are you deducing this from similarities?
I wish Andreas Rumpf were here to comment and hopefully correct me, but I believe he was formerly an ObjectPascal/Delphi programmer. The first version of the Nim compiler was written in Borland's ObjectPascal dialect (see http://nim-lang.org/docs/intern.html), which has some of the same features as Modula, but with a slightly more circuituous lineage, since it was originally based on Apple's Object Pascal, a dialect which Wirth was tangentially involved in designing. (Object Pascal predates Modula-3, too.) In that sense, some of the similarities are probably accidental or caused by cross-pollination (for example, Borland probably took the exception handling syntax from Modula). That's the problem of trying to infer lineage by looking at similarities alone.
The unified call syntax sounds like it might be lifted directly from Modula, though.
Macros implemented with ... string interpolation? This looks like a suboptimal idea.
Edit: I spoke too soon. This looks like code generation, and I guess that you ultimately have to do stringy things at some point. But couldn't there be some kind of type-safe mechanism for this?
You could also use other concrete types, generics and type checked or unchecked expressions instead of string.
Macros are syntax tree transformations, similar to rust compiler plugins:
import macros, strutils
macro readCfgAndBuildSource(cfgFilename: string): typed =
let inputString = slurp(cfgFilename.strVal)
result = newStmtList()
for line in inputString.splitLines:
# Ignore empty lines
if line.len < 1: continue
var chunks = line.split(',')
if chunks.len != 2:
error("Input needs comma split values, got: " & line)
let entry = quote do:
const cfg`chunks[0]` = "`chunks[1]`"
result.add(entry)
if result.len < 1: error("Input file empty!")
readCfgAndBuildSource("data.cfg")
This reads a file and creates constants from it at compile time.
Emit is a tad more complex. Nim is compiled to another language like c, c++ or llvm. Emit lets you emit code in the host language, mostly to wrap libraries. Don't think there is any way to make that typesafe.
Anyways, it looks like this is a code emitting example? I'm guessing the average user would never use that feature. I don't now nim but this is just an assumption. So I think we can let this one pass.
I do appreciate Nim, and bought Dom's book, but I feel it's missing a trick in its current state. No doubt I'll try it again as I'm ever the optimist :-)