
Nim Language Draws from Best of Python, Rust, Go, and Lisp - vasili111
http://www.infoworld.com/article/3157745/application-development/nim-language-draws-from-best-of-python-rust-go-and-lisp.html
======
Drup
Nim always looked to me as a modern version of OCaml made by someone who has
no idea how to do static type systems properly. The language as a whole might
have a nice feeling and convenient features, but the type system is really not
good ... D's type system, at least, is better designed.

On the other hand, I always considered Rust as the result of an ML programmer
looking at C++ and thinking "this is bullshit, I can do it cleaner".

I might have a very ML view of the programming world, but that's ok, most
other people have an ALGOL/C view of it. ;)

~~~
jackmott
yeah i have fever dreams of C and ML having some sort of super baby. rust and
nim are close but not quite

~~~
zem
some others worth checking out (all largely single-developer efforts):

[http://www.ats-lang.org/](http://www.ats-lang.org/) [ml + c + everything
dialled up to eleven. linear and dependent types. comes out of academia, but
under active development and slowly beginning to gather a community.]

[https://eigenstate.org/myrddin/](https://eigenstate.org/myrddin/) [not really
familiar with this one but it looks interetsing. close to the metal, has
pattern matching over algebraic datatypes but seems more towards the c than
the ml end of the spectrum from the brief glance i took.]

[http://mythryl.org/](http://mythryl.org/) [never took off, sadly; i really
liked the looks of this one and its ambitious goals. strong sml influence,
with better posix integration and some c-like surface features. developer is
currently battling cancer:
[http://mythryl.org/pipermail/mythryl/2016-April/000942.html](http://mythryl.org/pipermail/mythryl/2016-April/000942.html)]

[http://felix-lang.org/](http://felix-lang.org/) [spawn of ml + c++ rather
than ml + c. under enthusiastic if haphazard development.]

there have been a few others i've seen pop up over the years; i keep meaning
to make a website or at least a github awesome-style list cataloguing and
tracking them.

~~~
Drup
For all those propositions, I have only one question: Why would I use that
instead of OCaml ?

OCaml is far from being perfect, but it has lot's of features and a decent
community (especially compared to all those hobby/research languages).

OCaml can do pretty much anything except things like image processing and
video game programming. I mostly don't care about those things, and if I did,
I would use Rust.

Now, from a research point of view, sure, those languages are interesting.

~~~
zem
i'm in the same boat - i keep an interested eye on developments in the ML-
cross-C space, but so far none of them seems compelling to use over ocaml.
however, if one of them had a cross-compiler as good as go's, that would be a
killer feature. i would really like an ml-like language i could use to develop
desktop apps and trivially deliver binaries for multiple platforms.

------
mixedCase
The problem I have with Nim is that it misses the simplicity of Go and the
extra safety at high performance of Rust. At least _I_ , _personally_ don't
see the need for a middle-of-the-road language.

I wish them however the best of luck. Compiling down to C means being able to
leverage a lot of mature tools, and if they manage to simplify a lot of the
language they may rival Go for projects when you need high performance but
desire to retain high productivity regardless of how big and diverse your dev
team is.

~~~
beagle3
If Nim continues at the same pace, it may displace Python.

It is "as fun as" Python to start with, it has the knobs that made python
popular in many niches. It has official JS, C, C++ and Objective-C backends
(with perfectly compatible and natively fast FFI in each case). It compiles
down to small, efficient executables like Go does.

It has some of the best metaprogramming facilities (in a non-lisp language),
which makes it possible to introduce "source native" notation for e.g. XML and
JSON.

It also has an LLVM backend, though it is not yet complete.

Nim is a big and complicated language, but so is Python. The size of a
language itself is not a problem, as Python shows. Unlike C++, you don't have
to be familiar with every small metaclass/descriptor/base-class-lookup issue
to use the language. I believe Nim shares Python's "it's ok to ignore the
details until you need them" feature.

~~~
bsder
> If Nim continues at the same pace, it may displace Python.

Um, no.

Look at how long it took Python to displace Perl. And Perl was actively
shooting itself in the brain for _years_ or that probably wouldn't have
happened.

Python is far more embedded in certain areas now than Perl ever was.

~~~
flukus
Even python (3) is struggling to replace python (2).

------
sqeaky
I don't see the appeal of Nim. We have the choice of C++14, Rust and Go for
well supported robust languages with different focuses. C++14 has the best
execution performance, Rust is the most safe and it seems likely go tries to
be the simplest. What does Nim do better than any of these?

Presuming it does do anything better than those learning Nim is hard because
the examples are stale and the documentation lacking. I don't mean just the
official docs, which might be great, but where are all the answers on SO and
community made books or tutorials.

~~~
rbehrends
C++ and Rust don't have garbage collection, Go's type system is very
simplistic. Obviously, depending on what you do, this can be either an
advantage or a disadvantage. My point is that there are clear differentiating
factors.

The closest competitor for Nim is probably D, not any of the languages you
name.

~~~
sqeaky
The article seemed to describe a high speed native language with garbage
collection. I guess that does seem similar to D, but D is much closer to any
of the languages I listed with more than 15 years of development and a much
smaller list of breaking changes. It also isn't anywhere near as popular as
the three I mentioned.

Why does Nim get the attention that D does not? I think Nim only gets
attention around here because its new and not because it brings anything
directly useful. As long as it is still "new" there is still so much
potential.

As for garbage collection, I think you are overestimating its value. There are
great resource management schemes in both Rust and C++, and they can each
manage much more than just memory. I am only qualified to speak in detail on
C++, but if you simply avoid the "new" operator and automatically allocate
everything (some say stack allocate), which is the default, then everything is
cleaned up for you automatically.

Further down the garbage collection route, if your app doesn't need
performance then why not stick with Ruby, Javascript or Python, they are all
well supported and provide tons of flexibility and libraries. If you need
performance, why settle for have measures why not go for C++, Rust or one of
the blazing fast fully native languages without GC (even one of the really
fast ones with GC like Haskell or Java)? I see the space between them filling
up with a ton of languages that seem hard to distinguish. Nim looks like just
another, piling into this gap that swallows otherwise decent languages like D,
cyclone, darkbasic, pascal, and .Net language that isn't C# and so many other
languages that I cannot count them.

~~~
rbehrends
> The article seemed to describe a high speed native language with garbage
> collection. I guess that does seem similar to D, but D is much closer to any
> of the languages I listed with more than 15 years of development and a much
> smaller list of breaking changes. It also isn't anywhere near as popular as
> the three I mentioned.

Well, when you compare languages, you usually do it by feature set. Both Nim
and D are statically typed, garbage collected, imperative languages with
first-class metaprogramming features.

I'll also add that Nim has also about 9 years of development behind it. It's
older than you think.

> Why does Nim get the attention that D does not? I think Nim only gets
> attention around here because its new and not because it brings anything
> directly useful. As long as it is still "new" there is still so much
> potential.

I see both Nim and D getting comparable attention. They both aren't mainstream
languages, so coverage is mostly by enthusiasts and intermittent. People are
interested because both are sufficiently different from mainstream languages,
not because they suddenly plan to bet their careers on them.

> As for garbage collection, I think you are overestimating its value. There
> are great resource management schemes in both Rust and C++, and they can
> each manage much more than just memory. I am only qualified to speak in
> detail on C++, but if you simply avoid the "new" operator and automatically
> allocate everything (some say stack allocate), which is the default, then
> everything is cleaned up for you automatically.

This would be a long debate. Suffice it to say that for many people the
benefit of avoiding GC is unclear. Both C++ and Rust manage shared ownership
poorly (i.e. it being inefficient, leading to lots of syntactic noise, or
both). Note also that I'm not saying that GC is always better, but that it's a
differentiating feature.

As for resource management, RAII in my experience is primarily the consequence
of poor support for higher order functions or equivalent functionality in a
language. (The type of resource management that RAII facilitates is usually
better done through higher order functions or a sufficiently expressive macro
[1] system.)

> Further down the garbage collection route, if your app doesn't need
> performance then why not stick with Ruby, Javascript or Python, they are all
> well supported and provide tons of flexibility and libraries.

You seem to be have some serious misunderstandings about garbage collection.
No, GC is not per se a performance drain, and adding the two orders of
magnitude overhead that a typical bytecode interpreter for a dynamically typed
language induces is not even in the same ballpark for even poorly implemented
GC.

[1] And by macros I don't mean C/C++ preprocessor macros, but macros that are
properly integrated in the language and its type system, such as in LISP, Nim,
D, or Rust.

~~~
gpderetta
>Both C++ and Rust manage shared ownership poorly

Both C++ and rust encourage exclusive ownership. And that's a good thing.

> RAII in my experience is primarily the consequence of poor support for
> higher order functions or equivalent functionality in a language.

HOF tie resources to lexical scope; RAII ties them to object lifetimes,
recursively. In turn lifetimes may be bound to a lexical scope, but often is
not the case.

~~~
rbehrends
> Both C++ and rust encourage exclusive ownership. And that's a good thing.

It's not. It makes lots of important things unnecessarily hard and often leads
to unnecessary copying [1]. It makes it hard to even do something like OCaml's
List.filter and Array.filter properly. It gets in the way of doing functional
data structures (ex: binary decision diagrams). Lots of common design patterns
also require shared ownership.

> HOF tie resources to lexical scope; RAII ties them to object lifetimes,
> recursively. In turn lifetimes may be bound to a lexical scope, but often is
> not the case.

No, higher order functions don't per se tie resource management to lexical
scope (though that's the easiest application). You can build an entire
transactional model on top of higher order functions.

Second, tying resource management to object lifetime is dangerous, as object
lifetime can exceed the intended life of a resource (ex: closures, storing
debugging information on the heap).

Third, RAII is in practice little more powerful than lexical scoping. RAII
works poorly for global variables (problems with initialization/destruction
order) and thus is in practice limited to automatic and heap storage. Using
heap storage leads to the aforementioned problems, where object lifetime can
become unpredictable.

[1]
[https://news.ycombinator.com/item?id=8704318](https://news.ycombinator.com/item?id=8704318)

~~~
gpderetta
>It makes lots of important things unnecessarily hard and often leads to
unnecessary copying [1]

If you read the article referenced by that thread you'll see that a major
issue with string copying is due to having a lot of bad interfaces taking raw
C pointers so code at both side of the ibterface need to make copies exactly
because the raw C pointer doesn't guarantee exclusive ownership. The remaining
issues are due to a badly optimized string buider in Chrome and failure of
pre-reserving vector memory which lead to many copies on resize. This last
issue is fixed with move semantics in c++11.

>It makes it hard to even do something like OCaml's List.filter and
Array.filter

Std::remove_if works genrically on any range. Boost (and the range TR)
provides iterator views when you need lazy evaluation.

> You can build an entire transactional model on top of higher order
> functions.

I'm sure you can, in the end you can implement anything manually. With RAII
propagation of lifetimes is done automatically by the compiler.

>Using heap storage leads to the aforementioned problems, where object
lifetime can become unpredictable.

Only if you use shared ownership. Otherwise is completely predictable.

~~~
rbehrends
> If you read the article referenced by that thread you'll see that a major
> issue with string copying is due to having a lot of bad interfaces taking
> raw C pointers so code at both side of the ibterface need to make copies
> exactly because the raw C pointer doesn't guarantee exclusive ownership. The
> remaining issues are due to a badly optimized string buider in Chrome and
> failure of pre-reserving vector memory which lead to many copies on resize.
> This last issue is fixed with move semantics in c++11.

The point is that something like:

    
    
      List.filter (fun s -> String.length s > 0) list
    

simply cannot be done efficiently, because you require either copying or
shared ownership for the strings. This also occurs naturally in a number of
other situations, such as storing strings in objects.

> Std::remove_if works genrically on any range. Boost (and the range TR)
> provides iterator views when you need lazy evaluation.

std::remove_if is destructive. Iterators are not the same thing as a
functional filter operation.

> I'm sure you can, in the end you can implement anything manually.

The point here is that a transactional system is more powerful than RAII.

> Only if you use shared ownership. Otherwise is completely predictable.

If you don't use shared ownership, then you're basically limited to lexical
scoping.

~~~
charlieflowers
>> The point is that something like: List.filter (fun s -> String.length s >
0) list simply cannot be done efficiently, because you require either copying
or shared ownership for the strings. This also occurs naturally in a number of
other situations, such as storing strings in objects.

This is a _very salient_ point. It bounced around in my brain a couple of
hours before I came back to comment.

How often do you need to control memory layout and management so you get the
absolute best performance? Compare that to how often you need to express
filters.

For me, there's no doubt that expressing functional logic and having it be
decently efficient is the most important need.

This little example of yours illustrates that a well-designed garbage-
collected language has a HUGE advantage over RAII. I may be slow on the
uptake, but this is the first time I've seen it that way.

~~~
gpderetta
Filters are used all the time in C++.

* If the filtered result is used locally in a function (and then thrown away), a filtered view works just fine, is very cheap, efficient and is lazy (nice if you only consume a subset of it).

* Often only the filtered view is used, so you can destructively modify the original list, so no copies.

* If you need both the original list and the the filtered list, in a functional language you need to allocate new cons cells anyway. The cost of allocating, modifying and touching the new memory is going to dominate except for very long strings, so copying is not an issue.

Of course in C++ lists are frowned upon in the first place (as many algorithms
can handle any data structure transparently), while they are kind of central
in many functional languages.

There are cases of course where frictionless shared ownership is nice and GC
shines. Filter is not one of them.

~~~
rbehrends
> Filters are used all the time in C++.

The problem is that you need a vastly more complex machinery to cover all the
various ways to avoid copying/reference counting and then still don't have a
general solution when you can't avoid multiple ownership (unless you count
std::shared_ptr with its very high overhead).

As I said before, it's not that you can't do it, it's that there are costs
associated with it.

> If you need both the original list and the the filtered list, in a
> functional language you need to allocate new cons cells anyway.

You can filter arrays also and allocating cons cells for a list is pretty
cheap with a modern GC, as discussed before.

------
amyjess
There's also a lot of Modula-3 in there. Actually, the whole language is full
of Pascal-isms, but I'm not sure how many come directly from Pascal and how
many come via Modula-3.

------
rurban
But Wikipedia editors decided it is not notable, and speedy deleted it under
Nimrod.

After that debacle, Wikipedia decided Nim is finally good enough for them, and
they even link now Nimrod_(programming_language) to
[https://en.wikipedia.org/wiki/Nim_(programming_language)](https://en.wikipedia.org/wiki/Nim_\(programming_language\))

------
alexeiz
I don't know about Nim, but Infoworld is a pile of garbage.

