
On Learning Rust and Go: Migrating Away from Python - edward
https://blog.liw.fi/posts/2019/03/24/on_learning_rust_and_go_migrating_away_from_python/
======
jacquesm
15Kloc and trouble is indicative of other problems than a problem with the
language. I wrote multiple 50Kloc and up pieces of software in GFA Basic,
arguably a much more limiting and unsafe environment than Python ever was, and
yet, that software worked well and was maintainable to the point that its
descendants still run 3 decades later.

Python has all the bells and whistles you need to build large code bases, but
you do need to get organized, no language can really do that for you and
attempts at forcing you to do it give rise to 'factory factory' nonsense. I'm
no huge fan of Python, I use it when I have to but Rust is from a bells-and-
whistles point of view a step down from Python, it is more a better 'C' than a
better Python and Go has it's own share of issues that has kept me away from
it so far.

If you want to crank out some research project or application quickly building
on the libraries that others provide (especially in machine learning or other
data intensive fields) then Python would be my first choice, and something
like 'R' probably my second (though I see 'R' mostly as a data scientist's
workbench that has a programming language bolted on).

~~~
IshKebab
I disagree. 15k lines of code is a lot of code to keep entirely in your head
all at once, which is basically what you have to do if you're using a language
as dynamic as Python. In static languages like Java you can easily use tools
to check types are correct, find usages of variables, jump to definitions and
so on. And you get compile time errors if you screw up, rather than runtime
errors.

~~~
Bishonen88
Most of the above is due to a proper IDE. Python, too, has one _: PyCharm.
Comes with 'find usage of variables', 'jump to definition', types checking,
syntax correction, import optimization and much much more. 15k with pycharm is
a walk in a park

\_*More than one, of course. But I use only PyCharm :)

~~~
flyinglizard
It's nowhere near the capabilities of a good Java IDE; being Python, it's very
heuristic based rather than definitive. I know that searching for a variable
in Java would get me _all_ instances, no ifs no buts. Not so with Pycharm (or
any Python IDE).

I support the notion that Python is unsuitable for larger codebases with all
my heart.

~~~
joshuamorton
Surely not.

I can write reflection based Java code that will make automatic renaming
choke.

There are ifs and buts. They may be uncommon, but they're around.

------
lordnacho
I'm going to have a go with Rust and Go too, but for different reasons.

IMO Python is still the best language to go with when you are writing anything
"scripty":

\- Stuff that's not expected to be long. Do one thing well, let some other
program do another, compose the higher order functions from functions that
work. Of course this isn't always possible.

\- Stuff where the types are not going to confuse you. Often you just have a
few types, and it's fairly obvious what you can do with a given object. If you
get too many types, there's a good chance it will start to get confusing and
then strong typing would help.

\- Stuff where performance is not a problem. Don't write your HFT system in
Python. You simulation though, might benefit from orchestration of some VMs.

The ultimate use case for Python is glue code. And guess what, a lot of code
is just glue. A good glue language has a large ecosystem of libs, and some
language features that make it easy to read. That's Python in a nutshell:
whitespace formatting makes things easy to read, and you get built in
list/dict syntax to keep everything short and sweet.

For me Rust and Go are interesting having come from C++. There's a lot of
pitfalls in C++ that might be helped with Rust. At the moment I have a whole
load of Valgrind suite tests that look for potential problems. Perhaps Rust
can bake those into the language? I haven't had time to look at it yet.

Go seems to be interesting as a compromise between easy and fast, and by the
sound of it things have turned out well. I have people on my team using it,
and it seems to be the thing to do for web services that need to be faster
than nodejs but you don't want to spend a load of time making sure a c++
version is correct.

~~~
Annatar
There is one and only one language that's both correct and the best tool for
scripting: Bourne or its superset the Korn shell (not even bash).

~~~
theshrike79
From Google's Shell Style Guide[1]:

"If you are writing a script that is more than 100 lines long, you should
probably be writing it in Python instead. Bear in mind that scripts grow.
Rewrite your script in another language early to avoid a time-consuming
rewrite at a later date."

[1]
[https://google.github.io/styleguide/shell.xml](https://google.github.io/styleguide/shell.xml)

~~~
tannhaeuser
Well if Google says so ...

Python brings a ton of dependencies, thereby seriously limiting your
deployment options. And, together with Python's not-so-great package
management story, this spells a lot of trouble for as long as Python 2 and 3
need to coexist. Many useful Python 2 programs (such as Apple's old caldav
server based on twisted) won't be ported over to 3, and the migration to
Python 3 creates an unnecessary burden on apps that chose Python as user-
scripting language, such as Blender. There might be reasons to use Python, but
the aesthetics (or lack thereof) of a scripting language, or an artificial
limit on the number of lines most definitely isn't one of them.

------
toyg
_> Note that I've not written any significant code in either language, so I'm
just writing based on what I've learnt by reading._

So he’s basically comparing 20+ years of Python usage with marketing material
from Go and Rust. Right.

I wish people could be honest with their motivations, instead of making up
excuses to justify this sort of change. Here it’s a classic case of “I got
bored and I don’t like the new features, want new shiny”, wrapped in a bit of
whining about problems that have well-known solutions (use a good IDE, use
type hints or one of the many libs that enforce types...). I have no problem
with that, just don’t try to sell it to me on technical grounds, because it
looks very much like you have none.

Python is still one of the best ways to get stuff done, quickly and with a
minimum of boilerplate. Its limitations are well-known and have not really
increased for about 15 years - if anything they have shrunk in many, many
areas. Adoption rates keep exploding, despite a lot of doom forecasted by some
alpha geeks about 10 years ago: “There is no mobile story! We will all be
using Ruby/Go/NodeJS tomorrow! Nobody will ever go to Py3!” Etc etc etc.

You got bored by it? That’s fine, it happens, no harm done. But you don’t need
to convince anyone, including yourself, that you’re moving on because of this
or that flimsy excuse.

~~~
pagefault123
Perhaps there should be apostasy punishments for Python defectors. /s

Python's typing story is far from perfect and rather annoying compared to
other languages. Python is good for interacting with the operating system,
networking and other things.

But wanting a proper compiler is an honest motivation.

~~~
typon
Yet the entire data science world is built on Python. I don't understand this
blatant disregard of reality.

~~~
sfifs
Python is ideally suited for data science and machine learning because 80% of
the work tends to be data exploration, transformations and feature engineering
and 19% of the work is iterative development of models. In such workflows the
lack of type checking & simple REPL is a huge feature. Most of the underlying
code for ML is anyway written in Fortran or C and Python becomes a very
convenient front end glue

For the 1% work that is actually engineering the model's deployment in
production, it's not uncommon to use faster languages with the exported model.

If what you're doing is writing a vanilla CRUD server that gets thousands or
hundreds of thousands of hits a second, Python is probably a bad choice.

~~~
vonseel
I’m not sure how many people will ever even work on CRUD apps of that scale.

Even a mere 1,000 req/sec adds up to 86.4M per day. That sounds like something
at least as popular as Stack Overflow, for example. How many web apps are
there, really, that have millions of users?

~~~
pimeys
Or almost any advertisement tracker server.

~~~
vonseel
Isn't that market dominated by a few, or at the max, no more than 10-15
companies? My point is just that are there really more than a few dozen or
maybe a hundred companies that see more than 1000 req/sec (on web apps)?

~~~
tdfx
Depends if you're talking maximum or average. Getting to the front page of HN
could easily give you a burst of 1000 req/sec. I would agree there's very few
CRUD apps that deal with 1000 req/sec on average.

On the other hands, there's various APIs and tracking type of services that
probably do handle well in excess of that, being run by not-large companies
none of us have ever heard of.

------
buro9
I'm currently migrating a similarly sized Python and Django application to Go
but for different reasons.

For me it's bit rot. My Python is approaching EOL on this version and needs
upgrading to Python 3, and I have a lot of 3rd party code in here that made
things simpler to create but over time they've changed enough or disappeared
that I now have to take on work there too. Then Django and it's internals have
changed a lot in the last 6 years.

My Go code written at the same time (6+ years ago) hasn't had any of it's
libraries change so much that I've needed to do anything. Every now and then I
pull the next major version of Go and recompile and it's done.

This is all side project stuff but a lot of people use it (monthly average
visitors being +250k)... it's non-profit and I don't wish to have to maintain
it much.

It worked once, if nothing has changed in the functionality it should keep
working... but this isn't as true in non-compiled languages where you need to
depend on so much of the environment, let alone build culture that doesn't
fully vendor dependencies.

I like Python, but prefer to write code and move forward with other projects.

As to Rust vs Go. I code in both and only picked Go here because a lot of the
code in another project I worked on can be used here. I'd probably try Rust if
I was starting from scratch now. But I'd be a little concerned bit rot would
affect Rust too, it's still quite early for the wider ecosystem.

~~~
ris
What you're actually saying here is "Using Go I'm going to leave the
application with unmaintained versions of its libraries", which is a bit of an
alarm-bells statement from a security point of view.

It's perfectly possible to build a python application that is extremely
reliably tied to its dependencies, you just have to avoid the default python
package "management" solutions that get shoved down everyone's throat (pip,
virtualenv, pipfile, tox and the like). I've been building python projects on
top of Nix for years and have managed to maintain stable and reliable results.

~~~
empath75
“It’s easy to do it if you build your own dependency management system”
doesn’t sound like it’s easy to do it.

~~~
ris
Nix is not "your own dependency management system"

------
Animats
Having used all three of those languages, I've commented on this before.

Go is mediocre as a a language, but it has one big edge - if you're doing web
backend stuff, the libraries for that are the ones used internally by Google.
So they're being executed billions of times per second on Google servers and
tend to be well behaved. Python tends to have multiple libraries for basic
functions like the database interface, all with different bugs. If you write
web backend stuff in Go, it will probably work.

Having suffered through the Python 2 to 3 transition, I'm less of a Python fan
than I used to be. At some point, they need to stop adding features.
Currently, Python is acquiring unchecked "type hints", which look like a
terrible idea. Optional typing, sure, but unchecked type hints? If the
compiler enforced them, they might be worth something. (And no, running a
separate type checking tool is not the answer. Especially since no such tool
exists that's production grade and in sync with the language.)

Rust has no idea when to stop adding features. Rust started as an imperative
language and then morphed into a semi-functional language. Mostly to get a
sane error handling model. The borrow checker was a brilliant innovation,
though. I used Rust for a while, but quit about two years ago in disgust. I
never want to hear "that only compiles in nightly" again.

~~~
tomjakubowski
> Rust has no idea when to stop adding features. > I used Rust for a while,
> but quit about two years ago in disgust. I never want to hear "that only
> compiles in nightly" again.

I don't understand how you can reconcile these beliefs. They stabilized too
many features, but you also want more nightly-only features to be stabilized?

It's my experience as a Rust programmer since pre-1.0 that very few libraries
require nightly; they tend to be niche things (e.g. Rocket) by authors that
prefer to experiment on the bleeding edge of the language over having
stability or many users.

~~~
atombender
I suspect what OP is referring to is the fact that it's just hard to avoid
Nightly entirely, even if you don't need the new features.

All it takes is that _one_ library you want to use requires Nightly. Since
Rust adds features all the time, it's not uncommon for library authors to
start using these features before they're in Stable. It's just the nature of a
young language with an active community who likes being on the bleeding edge.

This also extends to the toolchain; it's not that long ago that RLS and
Rustfmt were still Nightly-only, for example.

The presence of Nightly alone gives you a choice that usually doesn't exist
with other languages. Not too long ago I went down the rabbit hole with some
text stream stuff (Unicode is surprisingly poorly supported in places), and
ended up with a temporary workaround because the std::io::Chars API wasn't in
Stable yet and I just didn't want to deal with Nightly. But it was tempting.
With other languages such as Go, the choice generally isn't there, even though
you could theoretically download HEAD and go from there.

~~~
burntsushi
It's not hard to avoid nightly at all. I've been targeting stable Rust in all
my applications and libraries since Rust 1.0 was released. The only exception
is adding a new nightly-only feature, but always gated behind an Cargo
feature.

This is a classic case of our standards of success continually moving, and
that some domains are better suited to stable Rust than others. For example,
if you want ergonomic async/await, then you need to use nightly. But
otherwise, the number of crates needing nightly has shrunk enormously over the
last few years.

> it's not uncommon for library authors to start using these features before
> they're in Stable

I would say this is actually pretty uncommon.

------
LawnboyMax
Strongly agree with author. I really like Python and at one point thought that
it makes sense to write almost any project in it, since it's so versatile and
I know it pretty well.

After working on a quite large application and having to use lots of
_assert(isinstance(arg, type)_ at the beginning of almost every function, I
began to think that a strong type system is very much needed for large
projects. I believe this was one of the reasons why Twitter moved from Ruby to
Scala.

I still love to use Python for hacking something quick for myself. But I also
look at some popular strongly-typed languages now and hope to get better at
one of them soon.

~~~
jsjohnst
> I began to think that a strong type system

You’re confusing static/dynamic and strong/weak. Python is a strongly typed
language, but also is dynamicly typed language.

Need proof? Try doing this:

a = 3

b = “3”

c = a + b

> having to use lots of assert(isinstance(arg, type))

Python has type hinting now, try using a current version of Python and this
isn’t needed.

~~~
mjw1007
I think that example shows that Python's type system isn't the weakest out
there, but it's still pretty weak.

For example, it doesn't have a built-in way to make a dictionary-whose-keys-
must-be-integers (so with your example above if you wrote thedictionary.get(b)
rather than thedictionary.get(a) you'd get an error rather than None).

I've often seen learners have trouble with this sort of thing (you read a
number from a file, neglect to call int(), and get mysterious lookup
failures).

~~~
UncleEntity
> so with your example above if you wrote thedictionary.get(b) rather than
> thedictionary.get(a) you'd get an error rather than None

Technically, dict.get() returns None if the item isn't found and you don't
provide a different value for its default.

thedictionary[b] would throw a KeyError on the other hand.

One could always subclass dict if they wanted to ensure the keys were always
integers or whatever.

> I've often seen learners have trouble with this sort of thing (you read a
> number from a file, neglect to call int(), and get mysterious lookup
> failures).

Not sure if you're arguing for a stronger type system or having the language
promote the string to an int as (I've heard) other scripting languages do.

Though, once you figure out the language doesn't automagically parse files for
you you're well on the way to finding more fun and exciting ways to get python
to throw error messages at you.

------
mark_l_watson
Thanks for The writeup, I am going through a similar process. I just retired
last Friday (I am an old guy) from managing a machine learning team and
everything was done in Python.

For personal projects (and past consulting work) I have been loving Lisp
languages since the 1980s but many languages have so many of the benefits of
Lisp (thinking of Haskell and Julia) and there is definitely a ‘lisp tax’ on
deploying and shipping products.

Anyway, for writing new books, writing open source projects, and perhaps some
consulting, I would like to cut back to a single language, instead of the 4 or
5 I use now.

EDIT: I did some Go Lang codelabs when I worked at Google and have played with
Rust (principally spending some evenings with an open source blockchain
project) and neither language will be my home base language.

~~~
pdimitar
If I retired today I'd try really hard to only use Elixir and OCaml.

Elixir is perfect for servers and fault-tolerance. Also scales quite well to
several tens of machines before needing any special tooling.

For a huge percent of most projects today Elixir would be ideal.

OCaml I want to use more for its really concise and strict (but extensible)
syntax. And mostly for its strong typing and really well-optimized compiled
native code.

Congratulations on retirement, relax and tinker at your own pace. ^_^

------
siteshwar
> Rust is developed by a community, and was started by Mozilla. Go development
> seems to be de facto controlled by Google, who originated the language. I'd
> rather bet my non-work future on a language that isn't controlled by a huge
> corporation, especially one of the main players in today's surveillance
> economy.

Anyone else agree with this view ? Programming languages should be choosen
based on technical merits, rather than who is behind it. Is there a lesson
from history that I am missing ?

~~~
bayesian_horse
In all three cases, Python, Go and Rust, the language and ecosystem may be in
the hands of an organization, but you can probably produce code productively
in it for years even if the organization went under or chose unacceptable
paths.

Go is quite unique in that it produces very independent binaries. This might
make software written in it quite future-proof.

Personally I like Python's philosophy and the way the community is run. I like
the trajectory. I understand the trade-offs. And I am sure as hell not going
to teach Go or Rust as a first programming language to people who aren't
computer science students. And even then...

~~~
vram22
>Go is quite unique in that it produces very independent binaries. This might
make software written in it quite future-proof.

What do you mean by "it produces very independent binaries."? Do you mean that
Go implements system calls itself, instead using corresponding wrappers from
the OS's underlying C library?

I read something like that recently, but haven't looked into the point yet.

~~~
bayesian_horse
"Very independent" doesn't mean totally independent. In particular Go doesn't
do shared libraries.

~~~
vram22
Cool, thanks.

------
xyproto
The strengths of Go become apparent when working in teams and when deploying,
not when reading blogs about the language before trying to write code in it.

~~~
empath75
I’m working in a team of 5 people who has never used go prior to 9 months ago
and had no training in it and we’ve just been unbelievably productive in it.
We came to it from a combination of python and javascript backgrounds and have
no problems collaborating or jumping into each other’s code.

To me the main advantage of it is that the small number of primitives and
simple syntax forces people to in general be very explicit about what you’re
doing. The code almost doesn’t need comments.

~~~
0815test
> To me the main advantage of it is that the small number of primitives and
> simple syntax forces people to in general be very explicit about what you’re
> doing. The code almost doesn’t need comments.

That has little to do with 'simple syntax', and more with the language itself
(and/or its community) setting clear standards as to what "idiomatic" code in
the language should look like. And Rust is fairly good at that, albeit with
the inherent limitation of having to support the additional complexity of
ownership/lifetime management. (Go can do without this since it uses GC
instead. Swift just uses ARC everywhere.)

------
xedrac
I'm a long time C++ developer, and recently took a job where I write a lot of
Python in a large code base. Initially it seemed great, but I quickly realized
how uncomfortable it is to have no safety net up front. The interesting thing
is Python eliminates a lot of programming errors you may encounter in C++. But
it introduces a whole different set of programming errors you would never see
in C++. I don't feel comfortable using Python for any project where the code
_must_ be correct. I would use Rust every time for that.

~~~
rujuladanh
Neither Rust nor C++ eliminate logic bugs (and no language can do that).

If you are writing code that must work, you should be either formally prove
the system (if feasible) or have a huge test suite covering everything.

~~~
apta
> Neither Rust nor C++ eliminate logic bugs (and no language can do that).

While true, it's a big benefit to eliminate classes of known bugs (e.g. memory
safe languages eliminate undefined behaviors, and Rust eliminates data races).
That allows the programmer to pay attention to other aspects of the code,
since there's only so much energy one person can spend.

~~~
rujuladanh
No. If a system MUST work, then there have to be no bugs at all. Removing a
class is useless. You have to remove all bugs.

You are talking about systems that SHOULD work, but aren’t required to always
work. Typically, safety-critical software is the latter, the rest of software
is the former. But the latter are entirely different beasts, and is what we
were discussing.

By the way, Rust does not eliminate all race conditions; and memory safe
languages may still have undefined behavior unrelated to memory (e.g. Rust)

------
0815test
Not trying to dismiss this person's work in any way, but is there any reason
why this blog post should be considered notable? They clearly say at the end
that they've yet to write any real-world code in either Rust or Go, and so far
have just been learning _about_ either language - so how come that this shoots
up to the top of HN? Is it just the magic keywords "Rust" and "Go" that do
that?

~~~
dpc_pw
I am a Rust fanboy, and I can't see anything worthwhile in this article. I
joke that any love-story about Rust will get you to a front page of HN. Yeah,
Rust is awesome, and many people love it, but it is a bit ridiculous.

~~~
vonseel
I wonder a little about the source of the name "Rust". That seems like an odd
choice for a language name - not that it matters. Rust - being associated with
old metals - makes me think of something that's been left out and abandoned.
Maybe because I'm from a rural part of the country where you see a lot of
rusted metal sheds or abandoned structures. Go, on the other hand, makes
perfect sense - "let's go!" implies that it is something that is made to get
things done and also being the first two letters of Google.

~~~
steveklabnik
It’s got multiple associations, the “well-worn tool” one is one of them.
[https://en.m.wikipedia.org/wiki/Rust_(fungus)](https://en.m.wikipedia.org/wiki/Rust_\(fungus\))
is another.

------
kumarvvr
At 15000 loc, if the author found it difficult to organize python code, then
it's not python's fault.

I find it a pleasure to organize code in python.

What am I missing here?

~~~
jacquesm
Exactly. 15Kloc is just out of the 'this stuff is easy' zone and switching to
Rust or Go will make that problem larger, not smaller (because you will need
more code to achieve the same effect).

~~~
pushpop
It’s not just about code organisation though. Both Rust and Go have fantastic
compilers which catch a great many dumb but common user errors before you even
get to the stage of testing.

Obviously this doesn’t replace the need for functional tests but writing those
tests is as much prone to user error as writing the code itself. So having a
compiler check for stupidity up front is always going to be a bonus.

Also the static type system helps a lot too. Having dynamic types can be
awfully convenient at times and I completely relate to why some people like
them but static types means your structures and classes effectively have
written specifications defined in the code itself which the compiler verifies
the rest of your program against. So if you’re accidentally trying to write
text to a numeric type, your compiler will catch that.

In my experience the extra up front overhead (in terms of development time) of
static typed AOT compiled languages end up saving you development time in the
long run when working against larger projects.

~~~
pytester
>Having dynamic types can be awfully convenient at times and I completely
relate to why some people like them but static types means your structures and
classes effectively have written specifications defined in the code itself
which the compiler verifies the rest of your program against. So if you’re
accidentally trying to write text to a numeric type, your compiler will catch
that.

In my experience, if I'm writing relatively decent tests and sprinkling of
sanity checks these types of errors get caught quickly and are very obvious.

I can sympathize with somebody who has largely worked with untested statically
typed projects and has moved to untested dynamically typed projects though -
this is where the benefit of compiler type checking might seem to be most
valuable.

I can also sympathize with somebody working with a dynamically typed language
with a _bad_ type system ( _cough_ javascript).

>In my experience the extra up front overhead (in terms of development time)
of static typed AOT compiled languages end up saving you development time in
the long run

Yeah, mine doesn't.

~~~
pushpop
Like I said, tests are also subject to user error. I’ve seen scenarios where
tests passed when they shouldn’t have because the test itself was wrong. Or
situations when test coverage was good but a basic type check seemed so
obvious it was forgotten to be added. Some of those tests wouldn’t even have
been needed in Rust or Go.

I do agree that tests are important; hence why I raised that point from the
outset. But ultimately in Python you’re still having to add extra tests just
to catch up with the default behaviour of Go and Rust. Which is the point I
was raising. Go and Rust are better at catching stupid user error.

Clearly though you can write large projects in Python if you’re disciplined
enough. Same could be said for C, BBC BASIC or even assembly. The question
isn’t whether you can, it’s whether other languages makes it easier or not.

~~~
pytester
>But ultimately in Python you’re still having to add extra tests just to catch
up with the default behaviour of Go and Rust.

You don't though. The tests you'd write which would catch these "stupid user
errors" are _basic_ ones which you'd be remiss not to write in _any_ language.

The fact that frequently developers _do_ choose not to write any tests at all
on large code bases does mean that they start to rely heavily on compiler
catching 'stupid user errors' but it doesn't have to be that way.

>Go and Rust are better at catching stupid user error.

...if you don't have a basic level of tests, yes.

(although rust does provide certain type level protection against, say, data
race bugs which python doesn't).

~~~
pushpop
You’re flip flopping all over the place with your descriptions of tests.
Broadly speaking, There are two types of tests being discussed here. Those are
positive tests and negative tests.

Positive being that the code does what you expect under normal operation.
Those you’d obviously need in any language

Negative tests are, amongst other things, checking that your functions behave
correctly when you put garbage in. If your compiler flat out refuses to send a
string type to a function that is designed to accept an integer then you’re
already covering a whole class of bugs without needing to write specific tests
for it.

~~~
pytester
>You’re flip flopping all over the place with your descriptions of tests.

The straw man of my argument living in your head flip flopped. I did no such
thing.

When I said "basic tests" I meant demonstrate the behavior under normal
circumstances". If you're doing TDD on 60% of your code base you'll write
enough of these.

>Negative tests are, amongst other things, checking that your functions behave
correctly when you put garbage in.

This is a completely unsuitable use case for a test. If your function expects
non-garbage it should raise an exception if it gets garbage with a sanity
check.

I wrote one just a few hours ago like so:

    
    
        assert no_nans(dataframe)

~~~
pushpop
I have no problems with exception _per se_ but what you’ve now done is push
your error checking into the runtime which means your application could crash
at unexpected times. This might be fine for your typical use cases but it is a
terrible way to go about building software if you’re writing headless
services.

The point of functional tests is they catch developer errors before your
codebase hits production. Which you cannot guarantee if your error checking is
only in the runtime.

Disclaimer: I write services used by millions of people (literally) each day.
Some of those services are written in Python.

------
sidcool
I have a genuine question. One of Rust's biggest plus points is having no GC
and the related overhead at runtime. Go, on the other hand does use GC. Then
how come so many successful Systems programs (e.g. Kubernetes) are written in
Go. Anything I am missing here?

~~~
amelius
Rust is still in research phase, as many programming patterns have no clear
counterpart in Rust. Even though Rust's approach is very interesting, it might
very well be that its strict typesystem turns out to be a dead-end for some
existing programming patterns.

Also, writing self-referential data-structures is very difficult in Rust (but
not impossible) due to the type system. I suspect that a lot of developers who
just want to get work done get turned off by fighting with the typechecker,
and choose GoLang instead.

And also: GoLang is a very accessible language, that can be mastered in a
couple of days.

~~~
0815test
> Also, writing self-referential data-structures is very difficult in Rust
> (but not impossible) due to the type system.

Not really true (at least, not nearly to the same extent) since Pin<> was
stabilized. I suppose that only serves to prove your point about Rust still
being "in research phase", though!

~~~
sidcool
Then does investment in learning Rust have any merit?

~~~
tomjakubowski
Yes. If your style of problem solving suits language features like pattern
matching on sum types and type classes, then Rust would probably be a more
productive language for you than C++, and it would be beneficial to learn it.

------
zachruss92
For me I think it comes down to what is the right tool for the job. I have
been using Python for years for web scraping & data analysis (via Scrapy and
SciPy) and I feel that they are the best tools for what I am doing.

Now that a lot of my scraping needs require me to render the DOM, I have had
to run a headless web browser (previously PhantomJS/Splash and now Chrome).
Chrome released the Puppeteer library which is the most straight forward way
to interact with Headless Chrome. This is in Node so that is what i’m using.

On my last project we needed to parse through a large amount of HTML files to
extract relevant information (about 70,000,000) and put it in a DB for further
analyses. I have done similar things in Python before, but there are
blocking/concurrency issues that can make it slow and frustrating to build.

My solution was to just do this in Go. I can then run my extraction in a
goroutine. Go’s selling point for me was speed (relative to Python) and dead
simple concurrency - which made it the right tool for the job.

Edit: Spelling, iOS’s autocorrect can be so annoying sometimes :)

~~~
justinclift
> parse through a large amount of HTML files to extract relevant information.

Any idea if Go has an equivalent to Pythons Beautiful Soup? :)

Back when I used to do Python development, Beautiful Soup was awesome for
extracting info from possibly-munged HTML. Haven't yet found a good equivalent
for Go. :/

~~~
theshrike79
I haven't found anything that matches Beautiful Soup's ability to parse
completely borked HTML.

For HTML that's at least mostly valid, I like goquery:
[https://github.com/PuerkitoBio/goquery](https://github.com/PuerkitoBio/goquery)

------
ChrisSD
This is more of a general observation but why are Rust and Go so often
mentioned in the same sentence? They are designed around very different use
cases such that a direct comparison doesn't seem to warrant as much attention
as it seems to get.

~~~
theshrike79
Both are modern languages but with (IMO) vastly different views on how a
language should be constructed.

Go went with simplicity to a fault. No generics (use code generation instead),
just one way to make a loop, garbage collection.

Rust on the other hand has all the bells and whistles a language could have
combined with the ability to micro manage every bit of memory you're using.

People tend to lean either way.

~~~
ChrisSD
But those different "views" are born of their different use cases. Rust is
meant to be low level, like C++, and thus micro managing memory is an
essential feature it can't do without.

Go is meant to be a higher level server side language that replaces languages
like php, python or Java on the server. It's simple so it's almost as fast to
compile as a scripting language is.

~~~
apta
Because when golang first came out, it was hyped as a "systems language", and
meant to compete with C++. Most people use that term to refer to languages you
use to write kernel level software. Of course, contrary to the golang author's
wishes, golang ended up being a competitor to python/nodejs/etc. but it's
still the case that the marketing hype from when the language first came out
affects what people talk about, even if they don't know the context of why
that discussion came about in the first place. Rust on the other hand, is a
(somewhat) viable C++ replacement, as can be seen in the projects that get
implemented in it (e.g. Rust made its way into the Firefox browser, as well as
other low level and speed critical networking projects at different
companies).

------
therealmarv
15K LOC in Python. Be prepared to increase your LOCs to at least 33-100% when
writing in Rust or Go, hopefully your error rate by line of code will decrease
more than your overall LOC. There are not only benefits.

~~~
weberc2
I’ve written a lot of Python and a lot of Go. The errors per loc are much
lower in the latter because code density is much lower and because of the type
checker. In other words, if you measured errors by statement or something more
meaningful than “line” then it would account for the difference in density,
but I would still expect far fewer errors in Go.

------
yawaramin
Folks may also be interested in a thorough analysis of porting a big Python
app (0install) to OCaml, after considering various alternatives like Rust and
Haskell: [http://roscidus.com/blog/blog/2014/06/06/python-to-ocaml-
ret...](http://roscidus.com/blog/blog/2014/06/06/python-to-ocaml-
retrospective/)

~~~
pdimitar
Thank you for that. I'm very interested in people's stories when migrating to
OCaml. Do you have more?

~~~
yawaramin
That's the biggest one I have :-) but you may also find this interesting:
[https://www.reddit.com/r/elm/comments/ac7n3e/philip2_an_elmt...](https://www.reddit.com/r/elm/comments/ac7n3e/philip2_an_elmtoreasonml_compiler_paul_biggar/?st=jtqesoe5&sh=be7a539d)

~~~
pdimitar
That's actually super interesting. Had no idea there was a way to migrate from
Elm to OCaml JS dialects so easily! Thanks.

------
mlinksva
The author's series on learning Rust, not linked in the OP
[https://blog.liw.fi/learning-rust/](https://blog.liw.fi/learning-rust/)

I really enjoy the author's blog, which has been discussed here many times
over the years
[https://hn.algolia.com/?query=liw.fi](https://hn.algolia.com/?query=liw.fi)

------
picacho
Every time reading someone changing from xxx to Rust feel the need to post
this thread, it's really fun indeed.

[https://www.reddit.com/r/rust/comments/acjcbp/rust_2019_beat...](https://www.reddit.com/r/rust/comments/acjcbp/rust_2019_beat_c/ed8ue2p/)

------
yakshaving_jgt
I share the author's sentiment, and it's what lead me to Haskell. It's faster
and cheaper for me to write prototypes in Haskell than it ever was in Ruby.

And at least in startup-world which is the bulk of my career, the speed at
which you can build a reasonably robust prototype can be the life or death of
a business, _and_ this prototype usually ends up being the production product
anyway. Prototypes are seldom rewritten "properly".

~~~
mlthoughts2018
I’ve worked professionally in Haskell across three jobs (one huge corp, two
start-ups), and seeing how bad Haskell functions in practice, when quickly
mutating state to incrementally modify behavior is live-or-die necessary and
under constant business pressures from product managers who don’t care about
the paradigm of the backend.

I’ve found so many unexpected runtime errors in Haskell, behavioral bugs that
require deep, stateful dependency injection to properly test for, type class
designs that were set up wrong for some use case last year and now are
horribly brittle and unmanageable to try to use it for the new use case that
needs customer feedback immediately.

Plus, for all the syntactical niceties of Haskell, the code becomes unreadable
the instant you start needing a dozen different GHC compiler pragmas all
defining weird special behavior or syntax. Yet it’s just basic Haskell 101
these days to require new compiler pragmas for tons of basic functionality
that you could get out of the box in other languages. Getting a whole team up
to speed on how to mentally keep track of that from one section of code to the
next is a very difficult chore.

My real life experience with Haskell is why I don’t use it professionally any
more.

~~~
yakshaving_jgt
I see. I guess I should rewrite my Haskell projects into something else then.
Yes, I am more than satisfied with how quickly I can develop features
according to business needs. Yes, I am more than satisfied with the [observed]
robustness. Yes, these businesses are currently 100% of my income. But as you
rightly point out, Haskell is _bad_. /s

A few things are interesting to me here:

1\. How we've managed to come to such different conclusions despite supposedly
having similar experiences

2\. The vigour with which you attacked my rather innocuous comment

3\. I had a look at some of your previous comments about Haskell, and you seem
to repeat the same talking points over and over, almost verbatim. In fact,
this comment you made is particularly interesting:

> it becomes the same shit code mess as any other paradigm.[0]

If what you say is true, then what is your argument exactly? If everything
inevitably produces the "same shit code mess", then why are you attacking me
for essentially saying "I like Haskell and it is working for me"?

[0]:
[https://news.ycombinator.com/item?id=19400648](https://news.ycombinator.com/item?id=19400648)

~~~
mlthoughts2018
I did not intend to “attack” you and I don’t believe that’s a good-faith
characterization of what I wrote.

I do attest to this same criticism of Haskell from time to time because I
believe it’s important to refute the very frequent, baseless claims that are
often made on Hacker News that claim that functional programming or static
typing can make any difference on the reliability or rate of defects in
software: they cannot and do not.

I’m not at all trying to dissuade anyone else from using Haskell if they want
to use it, and in fact I’d even go so far as to say Haskell is my favorite
programming language.

As long as everyone checks the wild claims at the door, and we all admit that
there is no difference in terms of safety, robustness, performance,
reliability, readability, etc., between Haskell, Scala, Rust, OCaml, Python,
Java, Go, Erlang, C++, C#, F#, C, FORTRAN, etc.

None of them is conceptually superior or dominant across a wide range of use
cases. It’s just as easy to get hard-to-fix errors in all those languages,
just as easy to categorically prevent other classes of errors, just as easy to
design for compositional or extensible interfaces, etc.

As long as everyone is essentially willing to accept a No Free Lunch theorem
about programming languages, then I don’t care what language people like to
use or happen to prefer for personal reasons. I’m not attacking any such
preferences.

But when there are unqualified comments about some paradigm or language (like
functional programming, or Rust, or Julia, or Haskell, or static typing) being
strictly better than some alternatives (like OOP or Python or C), then it’s
worthwhile to counter that claim by pointing out that no, in fact, all those
paradigms easily lead to the same problems and in no way offer any type of
widely applicable solution to the usual problems of developing software.

~~~
yakshaving_jgt
> I did not intend to “attack” you and I don’t believe that’s a good-faith
> characterization of what I wrote.

You were recently warned by a moderator to stop making sarcastic and
unsubstantive comments[0], so I don't think it's me who has trouble reading
your tone.

> I believe it’s important to refute the very frequent, baseless claims that
> are often made on Hacker News that claim that functional programming or
> static typing can make any difference on the reliability or rate of defects
> in software: they cannot and do not.

Any comments I have made regarding the benefits of FP and static typing are
anecdotal, and are therefore not baseless.

There's also anecdata like this[1], which further refutes the point you're
repeatedly trying to make.

> and we all admit that there is no difference in terms of safety, robustness,
> performance, reliability, readability, etc.

That doesn't match my experience. My experience has been that it is cheaper
for me to run my businesses on Haskell and Elm, as opposed to Ruby and [plain]
JavaScript. I've tried both approaches, and I perceive a difference.

> As long as everyone is essentially willing to accept a No Free Lunch theorem
> about programming languages, then I don’t care what language people like to
> use or happen to prefer for personal reasons.

I'll accept there's no free lunch — my technology choices aren't a panacea.
They do make a difference to my business however, and as a business owner I am
perfectly within my rights to make that judgement call.

> I’m not attacking any such preferences.

You certainly seem to be.

[0]:
[https://news.ycombinator.com/item?id=19241069](https://news.ycombinator.com/item?id=19241069)
[1]:
[https://twitter.com/rtfeldman/status/961051166783213570?lang...](https://twitter.com/rtfeldman/status/961051166783213570?lang=en)

~~~
dang
I don't see any attacks in what mlthoughts2018 wrote above. It's a strong
critique of Haskell, sure, but there's nothing wrong with that, as long as it
doesn't go into the programming language flamewar thing (which it didn't).

------
fxj
After all python is still an interpreted scripting language. To me comparing
it to rust and go is like apples and oranges.

~~~
jMyles
At a high level, I agree with what you're saying here - that it's difficult to
compare rust or go with python. But I take some issue with your reasoning.

> After all python is still an interpreted scripting language.

Is it? Or rather, is this even a well-defined category?

> interpreted

Can't _any_ (OK, almost any) language be either interpreted or compiled? The
fact that python is typically run in an interpretive runtime setting doesn't
really make it "interpreted" as a language. In fact, since python is nearly
always compiled to byte code at runtime, it's arguable just as compiled as it
is interpreted.

But that's not even the point: there's nothing lingual about python that stops
it from being compiled. It can be compared with other languages that are
typical run subsequent to a compilation step without being the apple to an
orange.

> scripting

This one speaks to me even less. For python to properly be understood as a
"scripting" language, I think you'd have to convince me that the lion's share
of community energy is dedicated to a paradigm of running a single module
front-to-back as a script.

And this is clearly not so.

~~~
codetrotter
I largely agree with what you said but

> there's nothing lingual about python that stops it from being compiled

Are you sure? Python is a _very_ dynamic language. Some of the most dynamic
parts of python might not be possible to compile fully ahead of time and might
need to be JITed, because the behavior of the code will only be possible to
determine at runtime.

~~~
darkr
CPython doesn't have a JIT. It compiles to bytecode, which is then
"interpreted" by a stack based VM.

------
qaq
I have reverse experience I've used pretty much everything under the sun, but
never really taken Python seriously just had to do a project in Python @ work
and it was such a pleasant experience so my current mindset Python + Cython
for most projects unless things are really perfomance sensitive than Rust.

------
julienfr112
Line of code is a relative measure. If you leverage package like numpy/pandas,
asyncio and co, you could easily write python code that are ten fold shorter
than their C/rust/go equivalent. And improving speed when you make a good use
of numpy requires quite an amount of time and skills.

------
sidcool
I am personally investing heavily in Rust. I hope to bear some fruit

------
Kronen
Go and Rust as substitutes for python, like really? If it works for you
perfect, but this is not serious even for a debate, generally speaking, for
the majority of programmers

------
timvisee
I like that you're approaching both Rust and Go, instead of just picking one.
Because a _war_ between the two on which is best seems to be quite common.

------
Annatar
"Partly it's because I'd like more help from my programming tools, such as
static type checking, better handling of abstractions"

As soon as I read that, I know immediately that I'm dealing with an object-
oriented programmer. Always the same gripes, always the same problems! Your
programming paradigm is busted and no language will ever be able to change
that, no matter what lexicography and grammar it implements! There is a reason
why procedural or functional programmers don't complain about those types of
issues!

------
_ZeD_
try java. no, seriously. java and a good IDE (netbeans or eclipse, not some
editors like vscode) are a godsend to handle "bigger" project. It's absolutely
fast to compile and insanely on-the-fly static checks all over the place.

------
coleifer
So a typically unimaginative python programmer sees new Kool aid and is
thinking about taking a drink. Decides to write blog post about it. And
somehow it's #1 on hn.

~~~
dang
Please don't break the site guidelines, regardless of how wrong you feel
someone else is. We've had to ask you this multiple times before.

[https://news.ycombinator.com/newsguidelines.html](https://news.ycombinator.com/newsguidelines.html)

~~~
coleifer
Which one did you feel I had broken? This post was just meme-filled gas.

~~~
dang
You broke the guidelines about name-calling, flamebait, and snark.

HN users need to follow those regardless of how bad an article is or they feel
it is.

------
coleifer
Dude wants a compiler and wants to go fast. And he picks rust? Guys been
hanging out way too long on hackernews.

~~~
tomrod
Why not Rust? I am in a similar situation to the author. Python handles most
of what I need, but that last 20% I need more.

~~~
0815test
The Rust compiler is well known for having rather less-than-stellar
performance, and this can definitely impact larger projects. (Much of the
problem is not quite related to Rust itself, but rather to the intermediate
compilation artifacts that are fed to LLVM for final code generation. It's not
exactly an easy issue to address, given that LLVM itself is rather old and
clunky code; written in C++ for maximum portability, not so much performance.)

~~~
civility
> Much of the problem is not quite related to Rust itself, but rather to the
> intermediate compilation artifacts that are fed to LLVM for final code
> generation.

Considering clang generates LLVM IR and compiles much more quickly than Rust,
this argument doesn't hold. The Rust compiler generates IR which chokes LLVM
and makes it slow, but they didn't have to do that.

~~~
steveklabnik
Yes and no; we can reduce the amount of it, but since we have different
features, we will pretty much inherently generate code that skips FastISel.
For example, “match” generates IR that’s not part of it. (See here for more:
[https://internals.rust-lang.org/t/why-cant-rust-use-llvm-
fas...](https://internals.rust-lang.org/t/why-cant-rust-use-llvm-
fastisel/2708))

It’s a huge problem with a number of different causes.

~~~
civility
> Yes and no;

Steve, this is a cop out. There's nothing in Rust that can't be implemented in
C or any other Turing complete language, including stack unwinding, invoke, or
anything else. It may be inconvenient for Rust to use or not-use some feature
of LLVM, but that's not the same thing.

~~~
steveklabnik
I think you mean well with this comment, but you're thinking about it
incorrectly. Imagine that it's possible to implement these features in the
FastISel subset; okay, we do that. Now, we're generating way more code. So
we're back to square one.

Being able to implement something does not mean that by implementing it a
different way, it will certainly be faster. And that's what we're talking
about here, compilation speed, not computational equivalence.

We find tons of bugs in LLVM due to using certain features (like noalias) that
are used a lot by Rust and very, very little by current C or C++ codebases.
That shouldn't be particularly surprising. Nor should it be surprising that
LLVM is mostly optimized for making C and C++ compilation times fast, and not
necessarily other languages.

Again, as I said, it's a complex, multi-faceted problem. You can't just say
"well, Zig compiles to LLVM, and it compiles fast, checkmate." That's not how
engineering works.

(And, note that FastISel is "This is a fast-path instruction selection class
that generates poor code and doesn't support illegal types or non-trivial
lowering, but runs quickly." So, the thing I'm talking about is a thing that
would help debug build times, but not production build times. I'm not claiming
that this one specific thing is the root cause of poor compile times, in fact,
I'm claiming the opposite: there are a number of different things that all
come together to lead to compile times being not as fast as we'd like.)

~~~
Annatar
"And that's what we're talking about here, compilation speed, not
computational equivalence."

I believe the original poster meant generated code when (s)he wrote about
compiler performance; the compile time is rather irrelevant for something that
gets done once; what's relevant is the speed of the generated code which then
runs the next billion times (or more).

So let's get back to the performance of the code generated by the Rust
compiler, shall we?

~~~
civility
If Rust didn't have good runtime performance, it wouldn't be worth looking at
over SML, Ocaml, or Haskell.

> So let's get back to the performance of the code generated by the Rust
> compiler, shall we?

"Shall we" just stick our heads in the sand too? No, you don't fix problems by
ignoring them or pretending they aren't a problem. Slow compilation speed is a
problem if you care about developer productivity and quality of life.

~~~
Annatar
Slow compilation speed is never a problem, I doubt anyone besides you cares
about it. What is important is whether it generates fast code. Taking a long
time to compile is fine if I get very fast code. I'm not going to be compiling
code anywhere near as many times as I'm going to be running it.

~~~
civility
You really think it's just me? Take care.

~~~
Annatar
I do. Computers for most people are tools to perform final work faster, not a
purpose unto itself which is all about programmer's convenience. A
programmer's job is to be as uncomfortable and to suffer as much as possible
so that the users could suffer as little as possible or not at all. This
"developer convenience" attitude should be reproached or even financially
penalized, so that such prima donnas finally come down to earth and start
taking responsibility for their (shitty) software.

~~~
civility
Compilers don't have to be slow to generate good code (at least not as slow as
Rust). If you prefer them slow, you're just choosing to be ineffective like
some idiotic martyr. Suffering for it's own sake is just stupid.

~~~
Annatar
I don't care about that, could not care less: I just do make -j 96 and go do
something else. The only thing that matters is very fast code. Back-end
optimizers cost CPU cycles, there's no way around that. Expecting fast
compilation times when iropt and lto have to do their thing is incredibly
naive. How can anyone in this day and age be so naive?

