I just wanted to say "Yay!" to Araq and the other major contributors to this project.
I have recently spent some time replacing Lua with Nimrod as the scripting language for my experimental game framework. I find the language beautiful and powerful.
My favourite feature of Nimrod is its natural, consistent syntax and the way powerful generics and overloading provide a means for me to hide the complexities of an implementation from the library consumer without sacrificing efficiency.
I have been keeping an eye on Rust and have been using Go every opportunity I get, but I have never been able to fully commit to any of them. Now my hope is that Nimrod will at the very least be the blueprint for the next, great systems language.
Nimrod is still developing, and there are of course issues. Mainly I am concerned with some oddities of the syntax (from the top of my mind: publishing symbols using asterisks, dereferencing refs using brackets, a bit excessive reliance on pragmas) but I trust these things will get worked out on the road to 1.0. There is a very beautiful, consistent language at its core with powerful abstractions that strike a fine balance between the heart-warming frugality of C and the expressive madness of C++.
Thank you and best wishes for the future!2014-02-23 22:06:48
Thank you, these kind words actually help to keep the motivation up!
The publishing by using asterisks keeps coming up and yet I challenge you to come up with a better syntax. Hint: These are not better, in my opinion:
export proc foo(a, b: int) # too verbose, not enough emphasis on 'foo' proc Foo(a, b: int) # uppercase as in Golang requires a *rename* just to export a symbol proc foo(a, b: int) export # weird, why not in the pragma section then? proc foo+(a, b: int) # how is + better than *? export # Haskell styled 'export' gets tedious, have to jump to the export list to add 'foo' bar, baz, foo2014-02-23 23:55:25
Good! When I get into it I'll try to help a bit with the code too. I don't know much about compiler design, but maybe I can do some good in the library-department.
I humbly accept your export-syntax-challenge:
I agree with your points. I can never quite decide whether the capitalization as publication syntax of Go is brilliantly simple or just plain annoying, but it was definitely a major paper-cut getting into the language.
There are two problems with the export-asterisk, the way I see it:
- Many people will come to Nimrod from C or C-like languages where asterisks are associated with pointers - especially as they appear in function declarations. Of course it just takes seconds to learn the Nimrod-way, but it just feels kind of inelegant to a C user since it does not map conceptually and looks kind of out of place anyway.
- Nimrod feels esthetically related more to Pascal and Python, than C. This is a landscape where things are spelt out, rather than modified with typographic dingbats. I find both the asterisk and the curly-pointy-pragma-braces awkward next to the rest of Nimrod.
This is inexact matter and you may of course disagree with any or all of the above, and there is little I can do about that.
If you prefer a typographic solution for its compactness, I would have preferred a different character. Preferably one with less C baggage. Consider the exclamation mark, then. It's the C not-operator all right, but it is never used in conjunction with declarations. It has a history with ruby where it is allowed as part of a symbol name and conventionally used to mark self mutating methods. Using it as an export qualifier makes more sense than either of those, in my cocky opinion. We could "shout" the symbols into the public.
proc foo!(a, b : int)
This addresses my first concern, but obviously not my second.
Modules might get quite complex. For the implementer/reader of the actual module code it makes sense to group definitions together in some logical manner probably grouped by the concepts or classes that each group of declarations define/implements. But when I am in the api-consumer state of mind I need a map of the public aspects of the module. I think an export-section is worth the hassle, especially with Nimrod-style declaration blocks which would allow comments interspersed with my symbol lists:
# A comment describing the purpose of the module export # A comment outlining the major types of this module type TNode, PNode, TSprite, PSprite # A comment motivating a section of the api proc foo(a : PNode, b : int) proc bar(a : PNode, c : int)
Specifying the parameters of the procs, templates and methods might get tedious, so maybe the asterisk could be reclaimed as a wildcard meaning "export all symbols of this name regardless of signature":
export proc foo(*)
Or perhaps better yet, just omit the qualifier and signature to export all matching symbols:
For simple modules with a natural "public" section of symbols, you could just combine the definition/implementation and the export like this:
export type TNode = object of TObject id : int proc foo(a : PNode, b : int) = ... code ...
Additionally "export" could be allowed as a prefix to allow inline exports (i.e. "export proc" and "export type").
An export-section would also allow a semantic feature that I wish for: In Node.js it is common to split a module implementation over several files and then present the consumer interface through an "index" module. That means there are several public symbols in the respective submodules, but you get to help point the library consumer towards the public symbols that are relevant from her perspective. I would love to be able to re-export symbols selectively from my sub-modules in such an exports section:
import window, widget, submodule3 export window.createWindow, widget.createWidget ...
Okay, this is my 7am Nimrod-novice stab at your challenge. Thank you for your attention.2014-02-24 06:52:59
maybe put the '*' next to the proc?
proc* foo(x: int, y: string)to
proc foo*(x: int, y: string)
The interesting part of this line is the foo(...). Taking the '*' elsewhere removes the emphasis from it.2014-02-24 09:08:47
> Consider the exclamation mark, then. It's the C not-operator all right, but it is never used in conjunction with declarations. It has a history with ruby where it is allowed as part of a symbol name and conventionally used to mark self mutating methods.
IMHO Ruby's history with ! is enough to disqualify the ! at the end, especially since it is a useful convention which could be interesting to have also in Nimrod..
> proc Foo(a, b: int) # uppercase as in Golang requires a rename just to export a symbol
If you don't have tools to do renaming in your code, you're doing it wrong(!), so it isn't such a bad idea..2014-02-24 10:59:18
> If you don't have tools to do renaming in your code, you're doing it wrong(!), so it isn't such a bad idea..
I don't think most editors currently support foolproof renaming in nimrod code. Besides, how can the tool know whether or not it should replace inside strings and comments? Renaming is not likely to ever be a completely-automatic procedure.2014-02-24 11:29:54
- > maybe put the asterisk next to the proc
- Then the same should relate to other constructs: template, type, var, ..., not only proc.
renoX: > could be interesting to have also in Nimrod..
- Agree. But without redeclaration, something like:
- having proc f(x: T): T and calling it like f(someVal)!, where someVal is an L-value, it makes someVal = f(someVal). There can be more arguments in the proc, the modification relates to the first one only.
- > just omit the qualifier and signature to export all matching symbols
The user of the module needs to see signatures, and rarely needs to see implementations. On the contrary, signatures may be optional in the implementation (only if there's no overloadings).
And then I think more handy should be to split modules into two parts (interface, implementation) by keywords without indentation, with only declarations allowed in interface section; this is used in some modules of the compiler now, with #implementation comment instead of keyword, e.g. compiler/astalgo.nim; they are very easy to read.
> Then the same should relate to other constructs: template, type, var, ..., not only proc.
Yes. Not sure how that might work with macros that produce new declarations - one would want to support exported and non-exported decls with the same macro.2014-02-24 12:10:53
- Export for symbol forwarding is already supported, so this works:
import window, widget, submodule3 export window.createWindow, widget.createWidget ...
- The asterisk as the export marker is not my invention btw, I took it from Oberon.
- The current syntax indeed works rather nicely with the macro system.
- Using an exclamation mark to annotate pass by reference is childish and Ruby code often doesn't follow this convention either. Nimrod solves the same problem by heavily discouraging chaining and with its explicit 'discard' feature. (Chaining also creates problems when it comes to lifetime and memory safety.)
- I like '!' instead of/in addition to '*' but I fear that might piss off the Ruby community.