
OCaml is Pretty Great (2019) - lelf
https://blog.chewxy.com/2019/02/20/go-is-average/
======
RcouF1uZ4gsC
I am happy that functions/subroutines were invented and in common use by
programmers in the 1970’s, otherwise we would have had arguments that function
calls with their stack based semantics are confusing, and explicitly writing
out what you want your code to do instead of hiding it behind a function call
increases code clarity.

There would have been a group of people who criticized Go’s lack of functions,
but other people would have pointed out that functions are not strictly
necessary and besides they will be added in version N+1 once we are sure about
the best way to do functions.

~~~
foldr
Subroutines themselves weren't the innovation. Everyone was already calling
out to subroutines in their assembly code. The innovation was structured
programming.

~~~
fpoling
Stack-based subroutine calls associated with structured programming came quite
after people started to use subroutines in the assembly or higher level
programming. Fortran, for example, gained those in eighties. Prior that
everything was statically allocated and recursive calls were not supported.

~~~
zozbot234
I'm not sure that "stack-based subroutine calls" are associated with
structured programming. An activation stack is required to ensure reentrancy
e.g. if a subroutine might be called from an ISR or a cooperatively-executing
task, in addition to suppprting recursion.

~~~
srean
Could you give us an example of a pre-structured programming, high level
language that supported the things that you talk about. PDPs had instruction
support for cooperatively executing tasks but the return address was stored in
a register, and was therefore limited to a depth of one.

From what I know stack based subroutines really became common around
Dijsktra's famous paper which really ought to have been called 'Use the Stack,
Stupid" rather than GOTO considered harmful. I am more than willing to be
corrected with citations to the contrary.

------
bufo
Have people actually looked at the code? You can’t treat the benchmarks game
code as a simple black box. Most implementations look like C regardless of the
language, eg. [https://benchmarksgame-
team.pages.debian.net/benchmarksgame/...](https://benchmarksgame-
team.pages.debian.net/benchmarksgame/program/mandelbrot-ghc-3.html) or
[https://benchmarksgame-
team.pages.debian.net/benchmarksgame/...](https://benchmarksgame-
team.pages.debian.net/benchmarksgame/program/nbody-ghc-2.html)

There is very little to infer from code which is so far from being idiomatic,
aside from the fact that you might as well use C if you ever find yourself in
the benchmark situation.

~~~
faccacta
Some other examples of what you are talking about: In the regular expression
benchmarks, some entries implement their own idiomatic regex parsers or link
to the PCRE2 library, rather than use the regex library that comes with the
language implementation: [https://benchmarksgame-
team.pages.debian.net/benchmarksgame/...](https://benchmarksgame-
team.pages.debian.net/benchmarksgame/program/regexredux-python3-2.html),
[https://benchmarksgame-
team.pages.debian.net/benchmarksgame/...](https://benchmarksgame-
team.pages.debian.net/benchmarksgame/program/regexredux-csharpcore-8.html)

This is, arguably, totally fine, because these are still valid programs that
run (and run quickly). BUT, it makes the benchmark programs poor choices to
compare the verbosity of languages. So statements like "For a language famed
for its terseness, Haskell it turns out, isn’t as terse as expected" can't be
supported when comparing benchmark programs that were written to maximize
speed, rather than written to minimize developer time.

Fortunately, the Benchmark Game does publish all of its programs, including
the ones that don't "win" the speed race, and it's possible to find nice,
concise, idiomatic Haskell programs in there.

~~~
igouy
> BUT, it makes the benchmark programs poor choices to compare the verbosity
> of languages.

Because?

Because the way some link to an external library is more verbose than the way
they link to an included library?

~~~
faccacta
Yes, that is what I mean. By the way, on the benchmark game website, is it
still possible to sort benchmark results not by speed, but by gzip'd source
code size?

~~~
igouy
On the task pages, click the column header:

[https://benchmarksgame-
team.pages.debian.net/benchmarksgame/...](https://benchmarksgame-
team.pages.debian.net/benchmarksgame/performance/regexredux-gz.html)

------
barbegal
Its a tough thing to study but I'm not sure the definition of verbosity is
particularly good.

>size of the clean (i.e. no comments, normalized white space) GZip’d program
source code, in bytes.

Some languages idiomatically use comments and white space to aid readability
whereas others use more verbose function and variable naming. Gzip will also
encode patterns that could be very verbose (switch statements, unrolled loops,
functions with same prefixes...) into very few bytes

------
zabil
My team's been using Go for the past five years to build an open source test
automation framework. None of us knew Go before starting on the project.

Five years on, we have no regrets. The language semantics does not get in our
way, it "feels" easier to solve problems. Personally, with OOP languages I
spend a lot of time designing vs solving. Design is subjective. Go, takes that
burden away.

~~~
fb03
I am doing the same with Rust. Fell in love with the language and it feels
great :)

Yeah you have to battle the borrow checker sometimes but it's there to help
you avoid shooting yourself in the foot.

------
jchw
Interesting but I find myself confused. There is not really much discussion
about what kinds of implications these metrics might have in practice and what
the limitations of this analysis are. Obviously the goals of programming
languages vary, and outside of esoteric languages few really strive to be very
terse. It seems at least a bit odd to me , then, to make value judgements
based on this.

Hate to be a wet towel, since it is interesting. But does it actually mean
anything?

~~~
apk-d
When it comes to picking criteria to compare languages with, performance and
succinctness have the advantage of definitely having a large impact on
developer productivity/happiness (same thing tbh) while being (relatively)
easily measurable.

Having recently jumped ship to a language/runtime that gives up to several
orders of magnitude of performance speedup while maintaining similar
verbosity, I appreciate the many opportunities this opens. I can write "lazy"
code that pretty much always runs (way) faster than the stuff I used to
carefully optimize. Perhaps the last metric I'd be interested in is the a
number of bugs in the average codebase, and while I've seen language
comparisons for that, I'm not sure whether to believe that they're accurate.

------
grey-area
_This chart shows the balance between the verbosity of a program written in a
language, and the runtime performance of it. The ideal programming language
would sit at the lower left quadrant._

This is a very odd way to rank programming languages. A language which said
nothing and did nothing would be in the lower left too.

I don't mind things being verbose if they are easy to read - compactness is
not a good measure of clarity. Code is read far more often than it is written,
so this is important, and performance is part of a set of tradeoffs against
resource usage etc, it's not a static thing for all situations.

~~~
ImprobableTruth
>A language which said nothing and did nothing would be in the lower left too.

Huh? This is like if I were to argue that I'm one of the top runners in the
world since I can't finish a marathon and thus my finish time is 0. A language
that is unable to solve the problems would not be listed at all or have an
infinite value on the performance axis.

>compactness is not a good measure of clarity

Solely taking compactness into account is definitely not a good idea, since it
just leads to code golfy situations. However, I completely disagree that
verbosity isn't a major detractor to readability, since it introduces a lot of
noise that detracts from what actually happens. People can only keep track of
so many things at once, so the simplicity of a single part often enough comes
at the cost at making it harder to understand the whole. It's not a
coincidence that 'higher-level' languages are generally less verbose than
lower-level ones.

~~~
grey-area
_A language that is unable to solve the problems would not be listed at all_

I was pointing out the absurdity of using these two criteria in isolation to
judge languages, turns out there are other important things like finishing
correctly, number of bugs, and clarity, not compactness. I don't think the
ideal language can be judged on two criteria (or that there is an ideal
language for everyone).

 _However, I completely disagree that verbosity isn 't a major detractor to
readability, since it introduces a lot of noise that detracts from what
actually happens_

Sure I agree extreme verbosity can be terrible too. So also can extreme
terseness, unless it closely matches the problem domain, because otherwise now
you have two problem domains you have to be familiar with in order to get work
done - the actual problem domain, and the jargon invented by the
programmer/language in order to solve it. This depends partly on the person
reading and their preference for abstraction.

------
dang
Let's try an experiment and replace the putdowney first part of the title with
its upliftey second part.

The experimental bit is this: since titles basically dominate discussion
completely, this change will probably convert a dyspeptic Go thread (boring)
into a vigorous OCaml one (hopefully less boring). Of course that assumes that
my posting this comment doesn't pull a Heisenberg on the discussion.

Edit: I forgot to mark this off topic so of course the meta aspect took over.
(This was the top subthread, probably overnight. I'm going to downweight it
now.)

~~~
MRMediocre
This is called 'misrepresentation'.

~~~
MRMediocre
Furthermore, by completely changing the title, you're grossly violating your
own guidelines:

"Otherwise please use the original title, unless it is misleading or linkbait;
don't editorialize."

~~~
Smaug123
HN is a benevolent dictatorship, which is a big part of why it remains such a
great place.

~~~
threatofrain
I'd look at various tech sub-reddits (like Rust) and ask why other communities
can do it with more transparency and better volunteerism.

~~~
dang
I'd be happy to learn from communities that get things better than we do, but
one critical bit for such discussions is that size is always a dominant
factor. At each order of magnitude, problems get qualitatively different. I'd
guess that the Rust subreddit is much smaller than HN (though who knows? Rust
is popular). If so, the lessons are not likely to translate automatically.
Similarly, lessons from HN don't translate to much larger outfits than HN.

------
smabie
The reason why Ocaml and Haskell are relatively verbose is that in order to
achieve maximum performance one must write code in a decidedly unidiomatic
style.

~~~
rwmj
This is true, but also not necessarily an objection. It gives you a choice of
decent performance by default, or very good performance when you really need
it.

~~~
k__
Reminds me of some blogposts abut JavaScript and Rust, I've read.

The author was arguing that you can achieve maximum performance with Rust
while still writing it in an idiomatic way, which isn't possible with JS.

~~~
tomp
That might be true, but the converse is that even idiomatic Rust is extremely
verbose and painful to the eyes.

Ideally, you'd be able to write mostly OCaml (higher level, closures,
polymorphism, GC) and Rust (safe manual memory management) only when needed.

~~~
pjmlp
Which will be possible when algebraic types get integrated into OCaml, part of
the work has already been integrated due to the ongoing multi-core changes.

~~~
tomp
You mean algebraic effects? Can you link to more about how the specifically
enable better memory management? I always though that would require linear
types (at least Rust-like memory management - I see how effects would enable
memory-pool / stack-like memory management).

~~~
pjmlp
Yes, sorry about the error.

Here are some papers about it,

[https://github.com/ocaml-multicore/ocaml-
multicore/wiki](https://github.com/ocaml-multicore/ocaml-multicore/wiki)

[https://github.com/ocamllabs/ocaml-effects-
tutorial](https://github.com/ocamllabs/ocaml-effects-tutorial)

~~~
tomp
I can't find any details on memory management (except regarding multicore GC,
which is not user-facing changes AFAIK).

------
tsegratis
Haskell's higher gzipped code size might be due to assignment providing
semantic compression for other languages -- that gzip isn't applying to
Haskell

I.e. gzip is very unlikely to model assignment in it's compression algorithm,
so it will compress other elements -- and those elements probably correlate
with the ones Haskell already optimizes for

So gzip metric makes the other languages look better than a pure loc would

~~~
amelius
Shouldn't two programs with the same function but written in different
languages zip to (just about) equal size, for a sufficiently powerful version
of zip?

~~~
CaptainRuhrpott
Such a version of Zip can't exist. If it would, you could decide whether a
program calculates a certain thing. According to Rice's theorem something like
that can't exist without solving the Halting Problem

[https://en.wikipedia.org/wiki/Rice%27s_theorem](https://en.wikipedia.org/wiki/Rice%27s_theorem)

------
bno1
Pretty great until you come across a project with thousands of lines of code
and 0 type signatures. At least Haskell warns you about top-level declarations
without type signatures. This is the error of the developer, true, but I think
compilers should steer people away from doing such things.

~~~
rwmj
For OCaml, generate annot files by adding the -annot flag. Then in emacs you
can do C-c C-t over any expression and it will tell you the type.

Edit: But I do think you have a point. In our OCaml programs we enforce
interface files (*.mli) for all modules (the rule is enforced by 'make
check'). So at least between modules there is always documentation and an
explicitly typed interface.

~~~
c-cube
In ocaml, install merlin or the upcoming ocaml-lsp, you mean :) It's excellent
tooling and provides completion, jump to def, etc. Annot files are very
limited in comparison.

------
AzzieElbab
I wish this post and comments had more ocaml :(

------
pansa2
> You may have noticed I left one of my favourite languages, Python, out. This
> is because I had truncated the chart at the given maximum X and Ys. Such a
> plot for Python would show no red line.

Is this because Python is very slow? If so, it would be interesting to see a
graph for PyPy.

------
cousin_it
Maybe a logarithmic performance axis would make the plots clearer.

------
dustinmoris
The original title of this blog post is "Go is a Pretty Average Language" and
the sub title is "But OCaml is Pretty Great".

Why has the title of this HN post been changed to something which isn't
either?

~~~
MRMediocre
Solely because dang didn't like the title. Here are several things to
consider:

1\. HN's own guidelines state: "Otherwise please use the original title,
unless it is misleading or linkbait; don't editorialize."

2\. dang edited the title of a submission from another user. Almost certainly
without asking.

3\. dang edited the title that reflecte title of an article verbatim, to
something completely different that conveyed completely different information.
Almost certainly without asking the author of the article.

It's HN's prerogative to do whatever they want on their site. However,
considering the after-the-fact manipulation of a HN user's post for no good
reason, and the misrepresentation of an article that someone else wrote, I do
not trust the HN mods at all. Since they're already changing user's
contributions based on a whim, it's reasonable to assume that this extends to
users' comments, the vote scores, and anything else visible on the site.

I'm going to get permabanned for this, and I don't care at all. I now have
zero trust in the mods of this site, and the information it presents.

~~~
dang
You're describing something that has been standard practice on HN for over a
decade, and is well understood by this community—so much so that entire
websites have been dedicated to tracking title changes on HN. If you want to
know more about HN, it's easy to learn by using the search box that's at the
bottom of every page, as well as the links (guidelines, FAQ, etc.) at the
bottom of every page. Also we're happy to answer questions at
hn@ycombinator.com, and HN users are happy to explain things to new users.

It's usually a good idea to take a little while to learn about the conventions
of a community you've just joined before jumping into high drama. On the other
hand, most new accounts that show up to complain about HN and its moderation
are not really new users at all, but concern trolls—sturgeon of the second
freshness:
[https://www.google.com/search?q=%22second+freshness%22&oq=%2...](https://www.google.com/search?q=%22second+freshness%22&oq=%22second+freshness%22).

------
bawolff
What a silly metric. Is there any point other then feeding language-war
trolls?

------
kumarvvr
Go and Rust are harder to pick up.

With weird operators and syntax.

Maybe I am getting old, losing my edge or python has spoilt me.

Even C# is elegant compared to those two.

I tried to learn both of them, but they just didnt excite me as much as C# or
Python.

~~~
ahartmetz
Rust has a similar "problem" as C++: it wants to be high level (for
productivity) and close to the metal (for performance). Such languages are
needed, but they are not going to be the easiest to learn. It is not their
fault.

~~~
m0xte
There has to be a simpler solution than Rust though. Rust seems to have
started with some clear objectives but evolved into a nightmare.

We should be putting the effort into the compilers and keeping the language
free of cruft and any unsafe concerns. Much like Delphi did for example.

~~~
rwmj
For most, average userspace programs garbage collectors work very well. (Of
course there are exceptional cases as I'm sure people will be quick to point
out.) However if you deny garbage collection for all programs you have to
replace it with something very complex to reason about, like RAII for C++ or
borrow checking in Rust. Or you end up reimplementing GC inefficiently (C++
reference counting). Also certain algorithms -- persistent data structures
with shared subgraphs and therefore cheap updates -- become very difficult to
write because there's no local ownership of nodes, only something with a
global program view (a GC) knows when an object is unreferenced and can be
freed.

~~~
tomp
It's funny that one of the key selling points of Rust is "fearless
concurrency", but IMO if you want _" real"_ concurrency - i.e. not just "split
work between threads" which is what Rust can do easily, but different threads
doing _the same work_ concurrently (e.g. accessing the same data structures,
sending messages, etc.) you need lock-free data structures, and for those you
_need_ GC (or something different, e.g. epoch-based reclamation - but from
what I've read (no practical experience though), it's just as tricky to
implement and performs worse than good GCs).

I think the future is combined GC (for concurrency & unpredictable lifetime
patterns) / reference counting (for resources - files, sockets, large
primitive arrays) / safe manual (e.g. memory pools). I just need to figure out
all the details :D

~~~
zozbot234
The crossbeam crate implements epoch-based GC for concurrency in Rust. It's
widely used and seems to work fairly well.

