Nim Programming Language v0.16.0 released
nim-lang.org
nim-lang.org
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 :-)
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.
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.
That was supposed to be "kitchen sink", but I guess this works, too.
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.
Not sure what has to happen for adoption but it's a real gem of a language that just needs users.
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.
Must have been a lot of work.
Check out the stdlib: http://nim-lang.org/docs/lib.html
Some interesting projects related to the above:
Webdev frameworks:
https://github.com/dom96/jester
https://flyx.github.io/emerald/
https://github.com/onionhammer/nim-templates.git
Gamedev:
Urho3D game engine wrapper: https://github.com/3dicc/Urhonimo
Nim GLSL framework (allows writing GLSL in Nim, meaning you can use metaprogramming in GLSL): https://github.com/yglukhov/nimsl
Roguelike api: https://github.com/Vladar4/libtcod-nim/
SFML lib: https://github.com/BlaXpirit/nim-csfml
SDL lib: https://github.com/PMunch/SDLGamelib
High level glfw wrapper: https://github.com/ephja/nim-glfw
Chipmonk wrapper: https://github.com/fowlmouth/nimrod-chipmunk/
Blog on writing a 2D platformer in Nim: https://hookrace.net/blog/writing-a-2d-platform-game-in-nim-...
Blog on making a JS NES emulator in Nim: https://hookrace.net/nimes/
It can easily be wrapped in a more usable API, for instance I have made mine: https://github.com/andreaferretti/rosencrantz
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
linagl: url: https://bitbucket.org/BitPuffin/linagl (hg) tags: library, opengl, math, game description: OpenGL math library license: CC0 website: https://bitbucket.org/BitPuffin/linagl
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
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.
1) Encounter unexpected behaviour with standard features
2) Ask irc for help
3) Response: shrug must be a compiler bug
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.
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.
ctwmelbjs16
It shouldn't surprise that the community is small. Please join and contribute and the language will grow.
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.
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?
Nim by example: https://nim-by-example.github.io/
Getting started with Nim: https://akehrer.github.io/posts/getting-started-with-nim/
What is special about Nim: https://hookrace.net/blog/what-is-special-about-nim/
What makes Nim practical: https://hookrace.net/blog/what-makes-nim-practical/
Introduction to metaprogramming: https://hookrace.net/blog/introduction-to-metaprogramming-in...
Writing a 2D platformer with SDL2: https://hookrace.net/blog/writing-a-2d-platform-game-in-nim-...
On the other hand, code without much typed macro transformations is really solid now, c.f. [0], the repo you are watching.
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.
If it could carve a small use case for itself, it would help it's momentum. Something to be recognized for.
- 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
type Vector* {.importcpp: "std::vector", header: "<vector>".}[T] = object
template `[]=`*[T](v: var Vector[T], key: int, val: T) =
{.emit: [v, "[", key, "] = ", val, ";"].}
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.
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.the `*` marker means that the proc/template is "public" (not local to the module)
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)
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"
> 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.
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 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:
https://docs.python.org/3/faq/general.html#why-was-python-cr...
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.
Thanks for the Python trivia, I didn't know that.
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?
const debug = true
template log(msg: string) =
if debug: stdout.writeLine(msg)
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.