Consider the Nimrod Programming Language
geetduggal.wordpress.com
geetduggal.wordpress.com
The language is actually pretty amazing — it's expressive and flexible (eg., type inference lets you omit types in most places, to the point that much of your code ends up looking something like Python/Ruby/Lua), and it's just amazingly fast, but not at the expense of ease of use. In almost every way, Nimrod is the "speed of C/C++, ease of Ruby" replacement that we have been looking for. Go's performance has been too disappointing, while Rust is a wee bit too complex. Nimrod feels just right.
As I wrote in a different thread, I and a colleague have been looking a little bit at using Nimrod as a game-logic language, as a replacement for Lua. Lua is pretty fast, but Nimrod is considerably faster; I'm personally also not a fan of Lua with its very weak table-based OO and rather idiosynchratic syntax, although I know it gets a lot of love on HN.
What makes Nimrod particularly suited to game development is that it's designed to integrate well with C. Nimrod compiles to C, and the generated C code provides the necessary bindings so that you can easily call Nimrod functions from C without an intermediate translation layer. In other words: If you write your core engine in C, scripting the game with Nimrod is (from what I can tell) as easy as with Lua. Very exciting.
How so? Everything I've read online has been roses and unicorns in terms of it's speed and build times.
And then there's memory consumption...
Additionally, in most benchmarks, Go does fairly well and is young and constantly improving: http://www.techempower.com/benchmarks/
You will also find Nimrod / Jester in those benchmarks, and can compare the performance for yourself.
gccgo has too many issues (lags behind release, requires gcc recompile, etc.) to be useful to most people.
We have to dig through 30TB of images -- so the performance benefits we got from gccgo were worth the trivial effort it took to implement.
I wouldn't say the syntax is complex because it's close to C++, but it isn't to everyone's taste (and that's fine; lots of people prefer that syntax and there's room for different languages for different folks).
More likely, probably people hate those two points so much that they forget to mention other problems. Which is a pity. Please tell us about other problems.
However, let's be clear that the pointer semantics do bring a great deal of complexity to the language.
That said, I'm very impressed that the managed pointer sigil has been eliminated and the feature moved to the stdlib. That and the fact that Rust's team has clearly pushed the message that owned pointers are the idiomatic way to deal with memory in Rust have combined to bring a lot of clarity to the language. Also, as stated above, I really like the direction that the standard library is taking. So congrats on a job well-done.
Edit: Let me also congratulate you on the Rust compiler error messages, which are almost invariably clear and actionable compared with other languages I'm playing with in this space.
Another similarity is uniform call syntax (which D calls uniform function call syntax, UFCS for short).
Also, you should need no more reason to avoid Scala than this: https://www.youtube.com/watch?v=TS1lpKBMkgg
If you're interested in Scala, learn Haskell. It's faster, its design is re-enforced with proven mathematical concepts, and it doesn't have the worst syntax ever.
You do realize there are quite a few commercial JVMs that generate native code AOT like any of the referenced languages, right?
Also, I think a lot of organizations would never approve using these in production, too likely that behavior will differ vs Oracle's or the OpenJDK VM's, the company won't be around in a few years, etc., and the gcj is very out of date from what I gather.
I don't know, but I guess enterprises do trust Aicas, Aonix, IBM, Excelsior and quite a few others.
Nonsense.
What are you talking about!? Have you even looked at either?
Nimrod:
for i in 1..100:
if i mod 15 == 0:
echo("FizzBuzz")
elif i mod 3 == 0:
echo("Fizz")
elif i mod 5 == 0:
echo("Buzz")
else:
echo(i)
Scala: for (x <- 1 to 100) println(
(x % 3, x % 5) match {
case (0, 0) => "FizzBuzz"
case (0, _) => "Fizz"
case (_, 0) => "Buzz"
case _ => x
})
In nimrod you'll notice a lot less parens, curly braces, and '=>'.> fast Haskell and easy/safe Haskell tend not to overlap as much as one would like
Not even remotely true. Where did you even get that idea?
I'm sorry, but the only people I've heard say this are those who are slightly open-minded about Haskell but truly believe it usually can't be remotely as efficient as imperative alternatives. None of the people I've heard make these statements have had even a few months experience writing Haskell.
If you can qualify this, I'd be pretty interested. Or if you've had an experience with Haskell that led you to believe this, I'd like to see if there is another solution.
I'm very interested in these limitations people always talk about with Haskell, but none of them have held up so far. I've been evaluating Haskell for a while and am very interested in testing any limitations you've faced.
Tabular nomenclature aside: Rust has values and two kinds of pointers, and a handful of built-in types, and you can have pointers to those types. While the semantics of the pointers are unusual, I don't think that makes it that much more complicated. It should also be noted that many of the proposed language changes make said table even more regular (e.g. replacing the [T] syntactic sugar for vectors with a more conventional Vec<T>.)
Rust is in some ways complicated, and I'll grant that a beginner to the language will likely curse the borrow-checker more than a few times. But I don't think Rust is nearly as complicated as it is sometimes reputed to be.
[^1]: http://cosmic.mearie.org/2014/01/periodic-table-of-rust-type...
[^2]: http://www.ozonehouse.com/mark/periodic/ is an egregious example.
[^3]: There are exceptions (e.g. the closure types) but they are few and easily memorized.
After a few days, the borrowing logic really started to click and I was fighting much less with the compiler. Admittedly, I still have some fogginess about some areas (particularly the borrowing/sending semantics of closures), but I understand that there's still some work left to be done on that before 1.0. But the point I want to stress here is that once the borrowing logic clicked, Rust became a reasonably simple language. Which is really important to me.
But, I now get to say that I just wrote quickcheck without manually freeing memory and without the use of a garbage collector. That's pretty damn cool if I say so myself.
Rust makes me uneasy because the whole lifetime tracking adds a lot of complexity and I fear it may make some programs harder to write or some libraries harder to use. Also I think that garbage collection, if fast (which nimrod's is very much so) is the right way to go in some situations. I don't actually want to go and spend time freeing a bunch of strings right after I use them.
You can use GC or reference counting in Rust—the same that Nimrod uses. (You could use DRC like Nimrod in Rust if you wanted, but it's not my preferred form of memory management due to the cost of making it thread safe.)
Definitely in some situations garbage collection is the right thing. But Nimrod's garbage collector is not thread safe...
> I don't actually want to go and spend time freeing a bunch of strings right after I use them.
That isn't how Rust works. The compiler automatically frees things via RAII.
Yeah the GC not being thread safe can be annoying. CSP works OK and if you need more performance a thread safe GC may not be fast enough anyway. If rust can pull off ownership tracking between threads in an easy-to-use way then I would be super excited.
Eager deallocation is usually what you want anyway, because of its cache effects and because you can just release the memory back to the free list (or the OS) and forget about it. If you repeatedly allocate and deallocate a similarly sized block, for example, eager deallocation means that your block will stay in L1 if it fits.
There's a separate heap per thread and data sharing among threads ins't allowed. It's perfectly thread safe.
Perhaps you should add two more things to your feature list:
1.) Native Perl syntax
2.) C imports for seemless use of C functions:
const txt = "x"
const x = 123
printf "%s is %d\n", txt, x // or
printf "%s is %s\n", txt, $x
I have been doing programming mainly with ToffeeScript in Node.js recently. I was worried that I might find dealing with some types and an actual compiler for a static language to be burdensome.
With Nimrod I have a syntax that's even cleaner than ToffeeScript and Python, which includes types inference to make type declarations minimal, and I actually find it easier to program with the type checking at compile time. Also my code is being compiled to C and then to native so it is very fast.
And it has very powerful standard library.
So what I have found is that not only does my Nimrod code execute vastly faster with much less memory than Node.js code, it builds much more quickly, and it is easier to read and maintain the code. One aspect of this is the fact that you don't have to use namespace qualifiers when you use module calls. Initially I was worried about that, since it is such a significant characteristic of Node.js code and point of pride for some. However, I think Nimrod has proven that this is the way to go. I can easily create my own DSLs with modules and extend the base programming system. This is something I tried to do with CoffeeScript because DSLs are powerful, but it was impossible to do it elegantly.
I have not yet attempted to learn the metaprogramming features, but from what I can see, few, if any, other languages with such high performance and clean syntax can compare with Nimrod in terms of metaprogramming.
I am quite glad that I found out about Nimrod before I got too caught up in Go or Rust. The syntax is much cleaner than Go, and the performance is better. The syntax is _much_ much cleaner than Rust, and overall its a much more practical language.
What I am doing now and plan to continue doing as much as possible, is moving my web programming into Nimrod code. Basically I am doing this because I need less memory usage in an agent I am going to install for a service. I briefly considered using C or something like that, quickly decided to take advantage of a newer language, started looking at Go, briefly got excited about Rust, saw Nimrod and fell in love. This is the language that is going to make it most practical to achieve my goals, as well as allow me to stay engaged by learning its more in-depth features as time goes on.
The only reason that Nimrod doesn't have instant uptake and popularity is that people don't evaluate things logically. Most people aren't capable of it, but even among the ones that are, peer pressure generally takes over. Humans are herd animals. They follow the crowd. If most people are driving cars that are four times as large as needed every day to work when they could just sign on to the internet and save gas, time, and the planet, then most people will do that, no matter how horrible it is. If most people choose a particular programming language even though it is inferior, then most other people are going to do that as well.
But you can still be like the smart guy who was driving the small, efficient, fast electric vehicle before electric vehicles were cool.