Nimrod: C + Macros + GC
nimrod-code.org
nimrod-code.org
But I think it suffers from the same fatal flaw that D does: you have to semi-manually translate C headers that you want to use. Like D, it provides an automated tool to help, but the translated headers will inevitably lag their original counterparts.
As another commenter below noted, the var and proc thing is also redundant and annoying. However, the ability to compile to C (and, as a result, to easily cross-compile) is really nice.
For example, there are the preprocessor macros. Most are straightforward, but it seems most C .h files succumb to the temptation at some point to do something wacky with them.
But I do still assert that this is a "fatal flaw" for a systems programming language. When I wrap a C library in, say, Python, I am already forced to write a wrapper layer, so there's no discomfort or surprise in declaring a few additional structs or function prototypes.
For a novel systems programming language, however, whose raison d'être is to save me keystrokes over C/C++, it feels like two steps forward and one step back to have a more concise main program but lots of auxillary handwritten header translations that have to be manually maintained.
I believe that the primary reason for the success of C++ is its easy compatibility with C, and any creators of would-be C++ replacements who fail to understand this are doomed to failure.
The main reason were actually
- Most C compiler vendors bundled C++ compilers in the begining
- The C and C++ compiler vendors that matter are OS vendors
Any language can replace C or C++, if an OS vendor decides that it is the way to go.
Lets say Apple decides to have Objective-C as their systems language, or Microsoft decides to have C# as their systems language.
Once upon a time, Apple's system programming language was a Pascal dialect, just as an example.
Developers are always at the mercy what languages are the official ones in a given platform.
This is how Microsoft is deprecating C on Windows nowadays, by leaving their C compiler at C90 level and stating C++ is the official systems language for Windows on their tooling.
Actually they've recently gone back on that and are implementing c99 language[1] and standard library[2] features in an apparent sudden realization that the rest of the C world has moved on (since they cite FFmpeg as a reason, my pet theory is that they were just that embarrassed by Ron Bultje's c99 to c89 translator[3])
[1] http://blogs.msdn.com/b/somasegar/archive/2013/06/28/cpp-con...
[2] http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-librar...
[3] http://blogs.gnome.org/rbultje/2012/09/27/microsoft-visual-s...
I can't think of a better alternative. Can you suggest one? The fact that Nimrod compiles to C already is a huge plus, it makes wrapping C code very easy.
Python goes with `=' for both creation and mutation of variables, and that causes some problems. So a separation of these might be useful.
var x, y: int
as opposed to the more concise C family way of doing it:
int x, y;
In C, there is no keyword needed to signal that this is a variable declaration. Similarly, in Nimrod, if you declare the return type of a function, you write it in addition to the "proc" keyword.
IMO, the C++0x/D way of declaring a type inferred variable/function, using the auto keyword, is superior, because it is an alternative to specifying the type, not in addition to specifying the type. The Python way, omitting the type entirely, is not really suitable for a statically typed language but at least has the advantage of brevity.
Even Herb Sutter, of C++ fame agrees:
> One of the things Go does that I would love C++ to do is a complete left-to-right declaration syntax. That is a good thing because the left-to-right makes you end up in a place where you have no ambiguities, you can read your code in a more strait-forward way, which also makes it more toolable.
(6:00) http://channel9.msdn.com/Shows/Going+Deep/Herb-Sutter-C-Ques...
var ptr_to_array_of_ptr_to_int : *[](*int)
would become something like this: *[](*int) ptr_to_array_of_ptr_to_int
The former syntax is slightly easier for a program to parse, makes it easier to see variable names, and is more consistent with typical syntax for type inference during variable assignment: var something := some_function(whatever)
auto something = some_function(whatever)
However, the latter does, as xaa said, eliminate some keystrokes. I also happen to find byte foo = 10
to read more nicely than any of these: var foo : byte = 10
var foo := (u8)10
var foo := 10'u8Type inference can be useful, but important secondary purposes of declaring types, beyond informing the compiler what type a variable is, are as documentation to yourself, and as a sort of compile-time assertion, to ensure that the variable type is indeed what you thought it was. Thus, a language with type inference should not treat manually declared types as some kind of corner case.
The "C family way of doing it" is problematic, and gets crazy complicated with more involved declarations (e.g involving function pointers and such).
Nimrods/Go/etc way is much better.
For example, they use the "var: type" syntax; the syntax for declaring classes is nearly identical; "case [value] of" is right out of Pascal, as is the "0..2" range syntax. They refer to "procedures" as opposed to functions. They even use naming conventions from ObjectPascal: "T" as a prefix for types (eg., TChannel), "P" for the Nimrod equivalent to pointers (eg., PChannel is a "ref TChannel"), "F" for class members.
I would not be surprised if the author was an old Turbo Pascal/Delphi hand.
A good HN day for language enthusiasts.
This really is an inconvenient time for the weekend to be ending.
http://www.techempower.com/benchmarks/#section=data-r6&hw=i7...
Has anyone used this in production?
For better evidence of Nimrod's power take a look at these benchmarks: http://togototo.wordpress.com/2013/08/23/benchmarks-round-tw...
Are there other Nimrod web frameworks (and importantly, domain experts with those frameworks) that could be contributed for Round 7?
Sadly, I am not aware of any other web frameworks. Speaking of Round 7, do you have an ETA for it?
test.nim:
var sum = 1.0
while sum<1.0e10:
sum = sum*1.00000001
echo($sum)
test.c:
#include <stdio.h>
int main() {
double sum = 1.0;
while(sum < 1e10) {
sum *= 1.00000001;
}
printf("%f\n", sum);
return 0;
}
C time / Nimrod time, average of 10 runs: 1.00 s = 1.0
while s<1.0e10
s = s*1.00000001
end
println(s)
Has mysteriously terrible performance. You have to use: function test()
s = 1.0
while s<1.0e10
s = s*1.00000001
end
println(s)
end
test()
to see what Julia can really do.1: http://togototo.wordpress.com/2013/08/23/benchmarks-round-tw...
> Beneath a nice infix/indentation based syntax with a powerful (AST based, hygienic) macro system lies a semantic model that supports a soft realtime GC on thread local heaps. Asynchronous message passing is used between threads, so no "stop the world" mechanism is necessary.
But if that kind of guaranteed cooperation isn't needed, I'd expect that lightweight threads could be added to a language like this in a straightforward way.
Disclaimer: I wrote this; it’s nowhere near complete, but not bad to play around with. We’re working toward a release in a few weeks, to include some missing language features and a new x86_64 runtime.
I'm really curious, as I personally see nothing good with them. The same kind of non-mathematical syntax as LISP (`1 2 +` as opposed to `+ 1 2`), without any of the goodness (code is data).
• They can be implemented very efficiently on real hardware. The stack-based VM is well established as an implementation technique for non–stack-based languages.
• Like in Lisp, the simple structure makes them suitable for useful visualisations beyond the program text. Static typing creates even more cool possibilities for such analysis.
• There is fertile ground for new research, and applying existing theory to these languages for the first time—particularly type and effect systems.
• It’s just a lot of fun. :)
// Implicitly thread state between functions.
def promptInt:
": " cat prompt
readInt
fromSome
// Write stacky code if you want.
def squareDiff:
- dup *
// Use locals as much as you need to.
"x0" promptInt ->x0
"y0" promptInt ->y0
"x" promptInt ->x
"y" promptInt ->y
x0 x squareDiff ->a
y0 y squareDiff ->b
a b + sayIntDylan: http://opendylan.org/
Euphoria: http://www.rapideuphoria.com/
Also it is still a great language for non-professional programmers and still has an active community there. Note the recently updated SDL2, SFML2, and Allegro bindings for example.
(implementation as MetaOcaml)
Defining characters as 8 bit is not quite correct (you will get char variables holding a fraction of a character), treating strings as arrays of characters by conversion also isn't (now you have an array of partial characters) and ignoring the encoding (just assuming UTF8) is a sure cause for annoying bugs - something the rest of the language goes great lengths to avoid.
I've only read the tutorial so far. Maybe the library fixes some of the issues - we'll see. The thing is just that if you start adding metadata to your sting types (they do encode the length (in what? Characters? Partial characters? Bytes?)), then why not also at least add an encoding (to help programmers not to mix strings of different encodings)? Why do everything right and then weasel out when you get to strings?
Sorry. I'm totally obsessive what string encodings is concerned :-)
http://forum.dlang.org/thread/uuevnvallcardcdjwikz@forum.dla...
It looks usable for soft realtime, almost keeping speed and control of C and adding ease (and fun) of coding.
GC is tunable and there are compilation options for embedded systems (http://nimrod-code.org/nimrodc.html#nimrod-for-embedded-syst...).
> The stdlib can now be avoided to a point where C code generation for 16bit micro controllers is feasible.
One thing that gets me, though, is the var keyword in a statically typed language. Why say "var thing: string" instead of "string thing"?
I think that consistent, explicit declaration of types is much cleaner and easier to read than this recurring mixture of type inference and annotation.
I bet the folks building these languages with inference probably and wouldn't mind having fewer annotations (and being more consistent, in a sense) if they could. It's just that to get rid of some of these annotations you have to make deep changes to the language, like OCaml's polymorphic functions, and that may be inconsistent with their design goals or just hard.
Obviously folks won't agree on whether inference is a great thing or not. Whatever one's used to usually seems easier to read. I've worked more in dynamically typed langauges than statically, and (so) languages with inference feel more like home.
In something like Scala, you can end up with some fairly hairy eyesores of variable declarations and the type is often not that important when you and everyone else have the ability to hover over a variable name and see the computed type immediately. Wouldn't work for a vim-driven language, but works well in an IDE.
It's a shame that a lot of these new languages focus on creating a really great language, but don't seem to give as much time to the practical usage of the language (for example, GHC did not support cross-compilation at all until very recently).
Ironing some of those fundamental issues out before adding some of the fancier features could probably really boost interest in the language and programmer uptake.
However they lacked the bundling to a commercial OS like UNIX, hence C grew in importance, because developers tend to use the languages supported by the OS vendors.
Because C++ is multi-paradigm, all paradigms are possible within it (although they may not be syntactically easy or have reasonable error messages, etc etc). Therefore, either C++ is the obviously the best language (to its partisans) or it is a hellish agglomeration of mutually contradictory confusing crap that takes years to begin to understand (to its detractors). Unfortunately, those two camps each find their position obvious, and seem to be unable to communicate with one another.
std::cout << "This does what??!" << endl;
Having said that any language with a GC is unlikely to supplant C++. I would have thought that anything that could get away with using GC is already not using C++. Ergo what will finally kill C++ in all its final domains is IMO some sort of better C. Maybe Rust, if they sort out their non-mandatory GC.
Technology changes fast, but humans take generations to be convinced of something.
Sometimes the only way for something to get adopted is when the luddites no longer have a word to say.
std::cout << "This does what??!" << endl;
If you're using namespace std then it's obvious (note that this is considered bad practice), assuming you haven't overridden <<, but otherwise it depends on endl's type and value. Maybe you meant std::endl?C++ is a wonderful language for people who like puzzles, and it's also good for making fun of know-it-alls.
Except trigraphs are another wart inherited from C (ANSI C section 5.2.1.1 A).
Nowadays I spend my consulting work in Java and .NET land, and actually I favour the Wirth family of languages over C and C++.
However, C and C++ have a big tooling support in the industry, and history shows system programming languages are only successful when backed by OS vendors.
What are those "sins"? What are the non-orthogonal constructs, and how are they "non-orthogonal"? What's unwieldy about them?
Seems mostly like pissing on somebody's work for the fun of it.
>> ...doesn't paper over the sins upon sins...
Please elaborate. I didn't see any of that and honestly don't know what "non-orthogonal constructs" means. I'm no language design expert but would like to know what, to you, are the obvious deficiencies.
For a language maintainer, this is another piece that will have to be supported, troubleshooted and documented.
The other problem for users is that it gives a sense of confusion and uncertainty (Paradox of Choice) about the correctness of a program that may lead to multiple refactorings that don't add any value. Also, more features require more learning and makes programs harder to understand.
The goals of any good language should be correctness and understandability. Arguably, Python learned the lessons from Perl. But there are many different languages, and some are better in different instances.
What Nimrod turns into will be hard to say, but Go and Erlang need more competition.
if yes("Should I delete all your important files?"):
echo("I'm sorry Dave, I'm afraid I can't do that.")
else:
echo("I think you know what the problem is just as well as I do.")Plus bytecode doesn't mean a program will run at all, look at all the java programs which run on android without modification, oh, wait...
I'm in CompBio too and actively avoid software distributed as just jar files. Give me the source so I can fix your (probably) broken software.
(Yes, I have a low opinion of the quality of software in my field.)
In my experience, biologists are allergic to the command line. They need web interfaces.
In the case where they don't mind using the command line, providing Linux x64 binaries (along with the source) is plenty sufficient.
Note that I'm not saying they shouldn't distribute the jar if that's the kind of game they want to play. I'm saying they shouldn't restrict themselves to distributing a jar.
> I do agree that the software should be open source.
Me too. But it's not an ideological point. I wasn't kidding when I said that, in all probability, I'll have to fix whatever software I'm using. Or at the very least, read the source code to understand what it is that they've implemented. (You'd think it'd be clear from the methods section in their paper...)
/rant
Doesn't mean that I am generally opposed to compiling to C, it's often a good trade-off.