Side-by-side Nim and Go
rosetta.alhur.es
rosetta.alhur.es
http://rosetta.alhur.es/compare/rust/c/
So it is not and is not meant to be 'fair', just a nice way to compare language idioms.
For instance, see "Box the Compass"; codewise the two aren't that different (Go is both slightly longer and appears to carry more information, it has more numbers in it for whatever reason), but the eye is initially misled by the fact that Go has a standardized formatting and the definition of a string array is rigidly required by the formatting rules to have one string per line, whereas Nim happily puts them on just a few lines. Neither is wrong, and, well, it goes back to that context I mentioned. Both languages have their reasons for that. Others, such as the matrix arithmetic, are pretty accurate... I think you're crazy to pick up Go and immediately start trying to do serious math, personally, but YMMV.
As a straight-up comparison of two languages, it seems to be fairly useless.
I'm definitely not going to bash Nim against Go, but to me, code like this:
proc det[M,N](a: Matrix[M,N]): float = let n = toSeq 0..a.high
is unreadable.
There's about as much (if not more) types of brackets in the Nim code compared to the Go code and I am moving towards an opinion that Nim is very unlike Python in readability (it may take things like indentation, no ";" and no " { } ", but Nim code is definitely not like Python in many other ways).
Also, apart from the brackets, it has things like:
"(a: Matrix[M,N]): float = "
which would not be clear to an average programmer unless he/she actually went out to "learn" the ways of Nim (whereas Python code is very readable, even if you just know basic programming).
Maybe this is due to the way the writer of each snippet writes their code, but as far as readability goes, Go wins on this one.
Nim:
proc det[M,N](a: Matrix[M,N]): float =
let n = toSeq 0..a.high
for sigma, sign in n.permutations:
var x = sign.float
for i in n: x *= a[i][sigma[i]]
result += x
Go: func determinant(m [][]float64) (d float64) {
p := make([]int, len(m))
for i := range p {
p[i] = i
}
it := permute.Iter(p)
for s := it(); s != 0; s = it() {
pr := 1.
for i, σ := range p {
pr *= m[i][σ]
}
d += float64(s) * pr
}
return
}
I don't know anything about Go or Nim, but the Nim version looks infinitely more readable to me.That's a (simple, standard) generic implementation, Go's is limited to a single type.
Is there anything else beyond the generic type signature that makes this less readable to you?
Also, if you like, you could change that first sequence initialization to: (0..a.high).toSeq to keep it consistent with other 'method' calls.
Fitting more on screen, and having a higher signal/noise ratio is /objectively better/ than otherwise.
Our industry loves to measure almost everything except human parsing efficiency. I'm fairly sure we could actually test this like we test anything else (and if the test says that's wrong then fair enough).
Does that mean that J/K/APL are the objectively best programming languages?
And defining what is signal and what is noise is pretty subjective. Pythonistas would say that braces are noise. Most people who use languages with braces would say they're signal.
- Minified code, including code written by humans that don't know how to name things, is quite obviously a separate issue, with a very different effect on parsing efficiency, than the use of unnecessary tokens.
- Of course existing programmers have biases. Measure parsing efficiency using people who aren't already programmers.
Responding to natedad below (rate limit):
> There are a lot of tokens which are not strictly necessary, but which make a programmer's job easier.
Which ones?
> There's more to designing a language than making it use as few tokens as possible...
Yes, but none of those things mean that efficiency is not important.
Responding to reitanqild:
My statement 'Minified code, including code written by humans that don't know how to name things, is quite obviously a separate issue' also neatly covers J/K/APL.
If there's anything else you've think I've not responded to, please actually state exactly what it is.
A lot of the choices in Go (and its standard formatting with gofmt) were made with all of these things in mind, not just the raw textual efficiency in mind.
But then you still need to adjust for skill levels, and that seems a bit circular.
I think we're far from being able to measure this accurately.
Japanese does not have key words that are already in English. This is why it's generally considered harder for an English speaking person to read Japanese than to read some simple code.
There are orders of magnitude more people who will program in future than which program now. We should absolutely design things around those people.
Edit for natedad: 100% of people that fixed a bug were non-programmers at some point.
But that's a separate question from how easy it is to use a language after you've already learned it. The studies to measure these questions would need to be designed differently.
On the other hand, these questions do overlap. People who know a language don't stop learning; they get better at using it with practice. Also, people who use a language occasionally need to switch gears going back to it and need to relearn things.
> NateDad: You state your view as fact, but you haven't considered some very obvious things that would normally be prerequisites to having that level of confidence:
Careful. You might be the one here who haven't considered some obvious things.
I think parent as well as dagw's comment (Does that mean that J/K/APL are the objectively best programming languages?) explaint perfectly well why what you wrote where flawed.
But the little I can see looks very promising, thanks for compiling this! Will definitely check back when Cloudflare has their act together again.
We should add consistent rendering in a browser to the Rosetta tasks.
Nim is no doubt more expressive and concise than Go, but this comparison is seriously unfair in some situations. In addition, although Go is concise on the absolute scale I don't think it ever set out to be the most concise - it solves the problems that it set out to solve.
[1]: http://rosetta.alhur.es/compare/nimrod/go/#Read_entire_file [2]: http://rosetta.alhur.es/compare/nimrod/go/#Zero_to_the_zero_...
Examples:
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
vs cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
and: if open == 0 {
fmt.Println("ok")
} else {
fmt.Println("not ok")
}
vs. if open == 0 {
fmt.Println("ok")
return
}
fmt.Println("not ok")Can't tell why. I think it's awesome. Languages like Ruby suddenly seem like they got a bunch of strange ends dangling all over the place.