Hacker News new | comments | ask | show | jobs | submit login

Rust is the answer to the question "can we have speed, correctness, and expressiveness in one language?" My company has been running Rust in production for awhile now, and it's exceeded every expectation. It's fast, it's safe, and it's so productive it's hard to find a reason to use anything else.

We've also found that the learning curve is, in our opinion, a bit overstated. We've ramped up several new grads on Rust with the O'Reilly Rust book. We see real productivity in about two weeks, which is actually faster than it was to ramp them up on our C++ code base. The compiler errors are amazing and it's almost like giving them a built in tutor.

I'm very bullish on Rust becoming the language of choice in the 2020s for everything from operating systems, web services, desktop applications, and more. It's that good.




I think the learning curve thing is depends on what's the language that you are compare it with.

C++ for example, is a hard language, but the learning curve is ... progressive (rise bit by bit).

Rust on the other hand, is like climbing a cliff: You're exposed to everything as soon as you start learning. That's all the Rust things (memory safety model and borrow etc) plus the rest of the knowledge that you need to learn when you normally learning a language (std library & stuff).

Luckily though, Rust did many thing in later years made it a little bit easier to use and learn. Like the rewritten books and manual and in my opinion most importantly few twists to the language.

My biggest (maybe nothing in the big picture) complain about Rust now is maybe it's too community driven, which can sometime cause minor fragmentation.

As a personal developer, if I've already followed every best practice writing my code, then to be honest, after the code is finished, I'm not willing to rewrite my code just to make it dated or work again (I mean, I'll pay my time to do it, but my hate meter will rise). Currently, Rust cannot fully deliver that.

I think Rust need strong leaders to layout a clear and stable plan, so more things can be standardized across it's ecosystem (Somewhat like what Go did, for example, io.Reader && io.Writer is life changing for me). In that way I can keep my hate meter at a safe level.


Traits for interop are a prime consideration for std, even if we try to keep it small. But we can only add things when they’re ready; that’s part of the stability you desire.

Look at the Future trait, as an example. And rust has had the equivalent of io.{Reader, Writer} since 1.0.


I know. But for me personally, the `io::Reader` and `io::Writer` is still not comfortable enough. Mainly because it's return values, `io::Error` to be specific. Because I found that in many of my cases, predefined `io::ErrorKind` is not enough for me, this results my abuse of `io::ErrorKind::Other`.

In Go, `error` is an interface that can later be asserted, so I can return any `error` then deal with them as late as I need.

This gives me ability to write some complex `io.Reader` and `io.Writer`. For example, an `io.Reader` that can Decode data stream, and returns both CodecError and IoError when it encountered any.

In Rust, if I want to write a similar thing, a HPACK decoder that returns both `io::Error` and `HPACK::DecodeError` for example, I need come up with another `Result` type that wraps both errors. This can sometime be tiring and makes the code inflexible (As one simple change to the `Result` may effect the entire call chain up and down).

BUT ... Maybe it's Go's fault, it treats me too well, make me want something that I cannot have for free (performance cost) else where.


> In Rust, if I want to write a similar thing, a HPACK decoder that returns both `io::Error` and `HPACK::DecodeError` for example, I need come up with another `Result` type that wraps both errors. This can sometime be tiring and makes the code inflexible (As one simple change to the `Result` may effect the entire call chain up and down).

Well there's stuff like error-chain to take care of the boilerplate...

Also, I believe you could define the equivalent of Go error in Rust as a trait and box it (ie. a trait object). It could be used much the same way as in Go with the additional benefit of Result being a sum type. I'm personally not a big fan of this approach but I guess it might work...


> you could define the equivalent of Go error in Rust as a trait and box it (ie. a trait object).

I know this basically how Go's error handling works (Put error data on heap and pass the reference), but I'm not fan of it (the put data on heap part of it) too :(

I will try out the error-chain, thank you for reminding me that.


The “failure” crate is an alternative to error-chain as well.


> I think Rust need strong leaders to layout a clear and stable plan, so more things can be standardized across it's ecosystem (Somewhat like what Go did, for example, io.Reader && io.Writer is life changing for me). In that way I can keep my hate meter at a safe level.

Just to add my opinion, not to disagree: I followed the development of Rust for several years now (starting before 1.0). Rust's approach to language evolution is very much community-driven (like you said). But this also led to many really good ideas coming from people with different backgrounds. Today, Rust feels like a highly optimized breed of good ideas taken from many programming languages and I know of no other language that feels like that. Sure, every new language gets inspiration from older languages, but Rust appears to be more "extreme" than other languages (and I do not mean "extreme" in a negative sense). This was most visible in the pre-1.0 era. People had different ideas how the language should work and the Rust team tried different things and iterated on the things they learned. And I think this was totally worthwhile.

Let's talk about Python for a moment. I really like Python. It is a language with clear conventions and idioms. And most likely it achieved this state thanks to Guido van Rossum who had very clear ideas about what the language should be. And one of the core ideas is simplicity. Python (being inspired by ABC) was meant to be easy to learn (because of it's simplicity).

Now, let's go back to Rust. Rust also has clear ideas: "Rust is a systems language pursuing the trifecta: safety, concurrency, and speed" (Quoted from: This Week in Rust). And yes, "consistency" or "ease of learning" are not listed as the core ideas. However, when you look at the Rust roadmap for 2017 you will also see that the team has prioritized the following items:

* Rust should have a lower learning curve

* productivity (which includes easier usage of the language)

These issues are definitely on the radar of the Rust team. But I also think that these issues can only be tackled by an entire community which shares and discusses ideas. Rust tries to be much more than other languages and I think it is highly unlikely that a single leader will know how to direct the language in a specific direction. There are still a lot of things to be figured out. For example, let's see if the failure crate becomes the standard for error handling in Rust.


<quote>C++ for example, is a hard language, but the learning curve is ... progressive (rise bit by bit).

Rust on the other hand, is like climbing a cliff </quote>

c++11+ is a hill that is so freaking high that you do not see the top.. like Olympus Mons.

honestly i do not see much difference in learning c++ or rust - in order to write good programs you should know most of the c++ standard and that's a lot to absorb.


Good point about the learning curve. I don't think Rust is especially difficult overall, but you need to understand a lot before you get anywhere. Haskell kind of have the same problem, where you need to understand advanced features like monads before you can even write hello world.


> C++ for example, is a hard language, but the learning curve is ... progressive (rise bit by bit).

Except that you've always got a footgun in each hand, with no safeties and no trigger guards.

Rust keeps its footguns locked in the gun safe. You get them out with the `unsafe` keyword.


> I'm very bullish on Rust becoming the language of choice in the 2020s for everything from operating systems, web services, desktop applications, and more. It's that good.

I don't mean to burst your bubble here. But people need to feel productive quickly with a language, otherwise they'll drop it and move to something else which makes them feel that way.

Looking at this thread there are plenty of examples of "I love Rust, but..." or "It's a great language once you get past...". My favorite: "There's an awesome web framework but you have to use Rust-nightly..."

Javascript is thought of as a terrible language by language snobs, and yet it has a huge following. Haskell, on the other hand, is much beloved, and doesn't. Don't get me wrong, it's got its share of love, but hasn't seen the explosive growth that python or java has.

The lesson from the early 2000's is that C++ may be a superior language to Java (I used to think that way), however people were so much more productive with Java. They didn't have to worry about memory management, segfaults, crazy C++ semantics, etc. Companies were more willing to throw hardware at a problem to reduce risk/time in development. And that is still true today.


> I don't mean to burst your bubble here.

You won't.

> But people need to feel productive quickly with a language, otherwise they'll drop it and move to something else which makes them feel that way.

This is relative. Rust is far easier to learn than C++. It has a compiler that will even enforce that you don't shoot yourself in the foot. It also has nice tooling to get you up and running quickly. It has good documentation. It has a free book. We've had no trouble getting our new grads up and running with Rust. It's not that hard.

> Javascript is thought of as a terrible language by language snobs, and yet it has a huge following.

Having a huge following doesn't make it less terrible by the measures of PL theory or sensibility. It's also the only choice on the web, but that may soon change, Rust has first class support for wasm so it's in a good spot there.

> Haskell, on the other hand, is much beloved, and doesn't. Don't get me wrong, it's got its share of love, but hasn't seen the explosive growth that python or java has.

By most accounts the Haskell ecosystem and user base are quite large considering it is intended as a research language, and the community is still growing. Rust isn't intended for research, and it's incredibly young compared to Java or Python, so it has plenty of time to catch up.

> but people were so much more productive with Java.

Hahaha. You mean people wrote a lot of Java. Let's please make the distinction between productivity and writing a bunch of enterprise crapware churned out by barrelful.

> They didn't have to worry about memory management, segfaults, crazy C++ semantics, etc.

That's exactly what Rust does for you.

> Companies were more willing to throw hardware at a problem to reduce risk/time in development. And that is still true today.

Actually companies are becoming more aware that speed is a feature, and that Moore's law isn't holding out. We're also moving to smaller form factors: phones, watches, glasses... the future is not on the desktop by any means, and no one wants to waste capacity in a datacenter needlessly.


See the thing is that I agree with most of your statements, so you're really not changing my mind with your arguments.

> Actually companies are becoming more aware that speed is a feature

No. If that were true, Python wouldn't be the fastest growing language, and we'd be hand optimizing everything in assembly and using languages that allowed us to do that (C). That was the entire point I was making. It's why Java won.

I can't figure out if Rust is serious about being a true competitor, or just merely riding the peak on the Gartner Hype Cycle [1].

[1] https://www.gartner.com/en/research/methodologies/gartner-hy...


Python is growing because it's a good scripting language, and there's a need in the ML community for a standard language to write scripts in. The ML community is growing like crazy, thus Python grows. Even though Python is secretly calling Fortran for scipy, or Tensorflow (C++), or PyTorch (also C++), all of which would make good candidates for Rust replacements. So obviously speed is necessary to enable what people are doing in Python.

I make the distinction between script and what we software engineers do, because I had the misfortune of spending half a decade in research doing ML, and those guys are not writing production programs. They're hacking out Jupyter notebooks and writing precariously balanced code that barely works.

That doesn't make Python suitable for large applications. It doesn't diminish the fact that CUDA is growing, SGX is growing, embedded is growing, that we're now unlocking 100G fiber, that we've reached the limits of single core performance, that intel is rolling out 8+ core consumer CPUs. Python is not going to shine for any of these things, but Rust will.


tl;dr: despite being relatively slow Python is a fantastic glue language. Some people thing rust is well positioned to steal Python's dinner.


To be fair, it's much more likely that Julia will be stealing Python's dinner, rather than Rust.


Django is not going to be rewritten in Julia. Neither is Linux going to be rewritten in Python. Different languages have different domains. Some of these comments seem to think all languages is competing in the same domain as if Rust is a direct competitor to Julia or JavaScript.


The context of the comment I replied to was that Python was fantastic glue code _for scientific computing_. Julia won't won't impinge on Django's usage share.


Rust will not steal Pythons dinner, they are used for completely different domains. The comment was saying that Rust might be a realistic alternative to C/C++/Fortran for modules which are not written in Python.


That's not what I said. I said Rust was a good candidate for all the things Python is using to actually do useful work. The underlying libraries written in Fortran, C, and C++.

Don't tl;dr; if you don't know how to r.


Speed matters, it’s just that it’s far from the top priority.

All else being held equal, developers and stake holders will choose the faster language, it just makes sense.

The trick is that speed is typically seen as diametrically opposed to usability, since quite a few languages achieve speed by turning all the safety rails off or existing way too close to the metal for comfort.

If rust could deliver speed without compromising on ease or safety, and I honestly don’t know if it can, then it will absolutely crush the competition.


Safety and speed are the big words on the box. Usability is harder, because it's somewhat a matter of opinion. As someone who has professionally worked with the expression based Haskell, Erlang, Elixir, and OCaml, I find Rust to extremely expressive. If you come from that camp and feel that OOP is a bad toolkit of abstraction and that higher order functions, typeclasses, type parameters, and ADTs are much more powerful, then I think yes, Rust ticks all the boxs.


> If rust could deliver speed without compromising on ease or safety, and I honestly don’t know if it can, then it will absolutely crush the competition.

It has to be more than safe and fast. It has to be a productive language to use. A dev can't sit for 6 months trying to figure out how to write a website, when he can pick up RoR and do it in a day.


That’s why I said “ease” too.


I think Rust should stop looking at C++ as the becnhmark / comparison point for complexity. The expectations that developers have from languages has increased over time, and Rust itself has contributed to raising that bar.


We don’t generally consider other languages as a measure of what complexity is “okay” or something, and are extremely aware of Rust’s complexity. Rust has a lot of requirements that directly lead to a lot of that complexity. But it’s neccesary, not incidental. Or that’s the hope, at least. Rust is also not perfect.


A lot of (but not all) complexity is solved in C/Python/Java by throwing a data structure at the problem. But is it a fair statement to say that not all data structures will work in Rust? Or is it better to say that some data structures work better in Rust than others?


Writing certain data structures in safe Rust can be hard, but not impossible. I’m not aware of any data structures that simply cannot be written in Rust.


Of course, since anything that can be written in C can be written in unsafe Rust.

Though, reading the post above yours, I was thinking more about the use of data structures than the implementation of them. In C++, when faced by the need to efficiently iterate through a data structure in different, incompatible orders, the tool of choice is often just to make intrusive linked lists with multiple next pointers per element. I think I've even once implemented something that was a priority queue (heap), two different lists and a tree at a same time.

While doing that in Rust is by no means impossible, it seems to me that the use of such a structure would be much more clumsy in Rust, to the point where I would try hard to solve the problem in some different way.

The languages are all turing-compatible anyway, so it's not about what can be done, it's about what approaches does the language make easy and promote. Overall I really like the kind of code idiomatic Rust tends to end up like.


Thanks for the thoughtful post. I do have a question, that maybe you can answer?

> The languages are all turing-compatible anyway, so it's not about what can be done, it's about what approaches does the language make easy and promote.

Turing completeness is kinda besides the point. We probably wouldn't be talking about it on HN if it wasn't. :)

I guess what I'm wondering is does Rust encourage simpler but possibly slower data structures, or are there some complex data structures which are simpler to ensure safety than other simpler ones?

In other words, does Rust encourage simplicity at the cost of speed?


As with all performance questions, the answer is “it depends.” For a look into this question, see http://dtrace.org/blogs/bmc/2018/09/28/the-relative-performa...


Hey thanks for the response.

I'm happy that rust has a good set of performant data structures, but on the other I feel like it's too soon to say Rust is the big winner here as the author does. I've been very skeptical on fantastical claims by language promoters.

But taking the pain out of making common data structures is a good start.


I think if you'll look into the author's credentials he is far from a "language promoter."


Comparing Haskell to JavaScript is silly - JavaScript is popular because it is the only option in the browser. It has noting to do with the quality of the language itself. If VBScript had won, everyone would be using that. If Netscape had decided to use Scheme or Haskell as the scripting language, this is what everyone would be using.

Rust is competing in the space of C and C++, it is not competing against Java or Python. People are not gong to write operating systems in Python because it feels more productive. For simpler desktop applications you may have a point, but heavyweights like Word or Photoshop are written in C++ and Rust may be a realistic migration. JavaScript or Python is not.


>heavyweights like Word or Photoshop are written in C++ and Rust may be a realistic migration

Especially we've gotten used to so many of C++ shortcomings that we don't see them, but someone learning both Rust and C++ will (I'm sure) have a better experience in Rust. Even just the built in tooling (Cargo test, Cargo crates, rustup, etc.) feels so much more mature than when you're in 2018 looking at how to compile some C++ without an IDE.


Text editors like vscode and atom (electron) go head to head with sublime (c++). The dominant editor now is vscode.

For Rust to win it must be adopted by Gaming or gaming engines.


If Netscape had used Haskell the WWW might never has taken off. Or att least scripting it might not.


Despite Java's growth, C remains the language of choice for operating systems and C++ for web browsers, desktop applications, games and high performance web services.

Rust is really only competing with C/C++, not JavaScript or even Java (or Go).


Some of those reasons are political, not technical.

Like C on embedded vs C++.

On Windows large majority of apps are in .NET with some C++.

On OS X and derived systems it is all about Objective-C and Swift for desktop apps. C++ is mostly used for drivers, LLVM tooling and Metal shaders.

Android is Java with some C++.

ChromeOS is all about JavaScript.

So no, C and C++ have lost the desktop, nowadays they are used for the graphics composition engine, while the remaining APIs are built on top of it with another set of languages.

If Rust is supposed to beat C and C++ on the desktop, it needs to be able to integrate into the IDE tooling alongside the mixed language tooling experience.


C is not used in the embedded space for 'political' reasons but for the fact that in contrast to C++ you have full control over what your program does and don't have to worry about when certain functions get magically called and why the size of your two-int struct is suddenly way larger than the 64 bits you expected it to be.

Sure, this is all a matter of 'using it right', but from my experience many developers in the commercial embedded space are not programmers by trade and this learning those intricacies is a real hurdle for them.


Sure it is for political reasons when even C99 is seen as too modern, and many are unwilling to let go of C89 and Assembly even if the OEM toolchain supports modern C.

And for another point of view of someone more relevant than my insignificant self,

CppCon 2016: Dan Saks “extern c: Talking to C Programmers about C++”

https://www.youtube.com/watch?v=D7Sd8A6_fYU

"Embedded Development with Dan Saks"

http://cppcast.com/2016/10/dan-saks/

Thankfully there are industry certification standards like AUTOSAR, which now require C++, so those devs can choose to keep grasping to C and switch industry or learn more modern languages.


That's relevant when you target <1$, >.15$ processors, but they are rather niche.


I'm waiting for game engines to pick up Rust.


Not sure why downvoted. A language aimed at replacing systems languages like C++, which happens to be the go-to language for game development, seems like a reasonable choice for a game engine.

There's actually a website dedicated to tracking this - http://arewegameyet.com/


Actually it is quite interesting, thanks for sharing.

I think to be on pair with C++, a Rust based engine needs to have some Unreal like tooling.

Which actually seems to be a couple of WIP on that website, so I will now get to track their progress. :)


To be competitive to C++ on the AAA world, Rust engine tooling need to be on pair with Ogre3D, Godot, Cocos2d-X, SpriteKit, Unreal, Unity, CryEngine.

So it would be interesting to see what Seed Studios will come up with.


> Despite Java's growth, C remains the language of choice for operating systems and C++ for web browsers

Does it? Existing project use what they have chosen long time ago, we can only discuss choice for new ones. And new OSes often choose something else. I am not aware of any new webbrowser, so can't say anything about that.


> But people need to feel productive quickly with a language, otherwise they'll drop it and move to something else which makes them feel that way.

Yes, I agree, but that's not the full picture. People want a language in which they can be productive quickly, but once they master it, they, or at least some of them, will then look into quality and performance. Languages like JavaScript or Python (and even Go to some extent) are popular and easy to pick up, but there's not much room for further progress. JavaScript is already stretched to its absolute limits when it comes to performance and it's still not performing very well. And when it comes to quality, well, TypeScript is a thing for a reason.

I don't believe Rust will ever be as much of a language for the masses as JS, but it has a good chance to become a niche language for those who need or want more performance and/or quality than they can get with langs like JS or Python.


> Rust is the answer to the question "can we have speed, correctness, and expressiveness in one language?"

My biggest gripe is that they left out readability.

I like the semantics of Rust, and appreciate the performance and the transparent memory model. I am extremely excited to try Rust on an embedded project.

Bur honestly, the syntax is gruesome. Coming from Python, Rust looks like two rabid gerbils had a war dance on my keyboard.


>Bur honestly, the syntax is gruesome. Coming from Python, Rust looks like two rabid gerbils had a war dance on my keyboard.

What exactly is terrible about it? The snake_case I got used to, I kind of like having braces, and that's not really a killer argument either, because most languages have them, apart from that I find Rust also much cleaner than Python syntax. I'm really not sure what you mean. Is it the lifetime annotations (because they're somewhat necessary).


Okay, tell me if this is readable to you:

   fn accumulate<'a, T: Monoid>(tuples: &[(&'a str, &Fn(i32) -> bool)], i: i32) -> T
   where
        T: From<&'a str> + From<String>,
this is JUST the function signature

yes, every single thing in there is necessary, it can be written in a more gruesome way, but the where clause clarifies it a bit

But let me cheat a little bit

    ( $(#[$attr:meta])* enum $enumer:ident { $($i:ident => $e:tt $( ( $($m:ident),* ) )* ; )* } ) => {
how is this macro syntax looking?


#1 I find is not worse than C++, granted there's more complexity here than in Python but in terms of cleanness its ok IMHO. Because as you said there's nothing unnecessary. Rust addresses different problems than Python, so we should compare apples with apples.

On the second one you got me though, I find the macro syntax a bit horrible. Sometimes I just want simple text substitution.


C++ templates also aren't winning any readability awards.


I'm comparing it to Haskell syntax for the same thing, which is much cleaner


Haskell does not have borrowing and lifetime specifiers though, which is what makes the Rust example more dense.


Haskell has nice syntax for generics, no stupid <> to forward declare type parameters


It is somewhat unfair to compare this to Python, since a lot of the simplicity in Python comes from the semantics (dynamically typed, garbage collected and so on). Rust need to express all this information (types, lifetimes etc.), so it will necessarily be more dense. The question is if this information could be expressed in a more readable syntax. This might be possible, but I would like to see a suggestion of how.

I guess the signature could be made more readable by using a few type aliases. The hardest part to read is the nested types.

I'm with you on the macro syntax, it is very hard to read. It is not easy to create a readable macro syntax though. All languages I know have hard-to-read macros, so this is not yet a solved problem.


Here is a simpler syntax:

   fn accumulate tuples: &[(&'a Str, &Fn(i32) -> Bool)], i: i32 -> t
   where
        t: Monoid + From &'a Str + From String,
this is how Haskell with lifetimes and borrowing would look like (if arguments were not curried)


This is arguably less readable, because it's missing some delimiters for your eyes to latch onto.

It's also not realistically parseable- the Haskell/Ocaml-like removal of <>s and ()s relies on application being left-associative, and if you read this under that rule you've changed the meaning (e.g. `From &'a Str`).


I like removing superfluous punctuation, but if parentheses are removed from method signatures than they should also be removed from invocations, which in turn comes with its own set of readability issues. I'm not a fan of the $ operator in Haskell, for example.


This also reminds me that, in Python 2.x, the following code...

for i in range(100000000):

...creates in memory a list with one-hundred million integers.

Expressive yes, but sometimes it can be double-edged for new comers (and not new comers).


As someone with a C++ background who loves Rust and wants it to succeed: Code where the lifetime syntax is used much can look really horrible and confusing, and to people new to Rust it might feel like it's for no reason.


Well... compared to Python is kind of an apples to oranges comparison. Compared to Java or C++ I find it to be incredibly direct and expressive. Rust definitely doesn't stop you from writing spaghetti, but no language does.


I don't think the potential for spaghetti code is the problem, I think it's more the terseness of Rust code that makes it hard to read (speaking as someone who doesn't know Rust very well, but has a mild interest in learning it). I agree with the above complaint - it does feel a bit terse and that makes it harder to read IMO.

Languages like Java are more verbose which does make it a bit more frustrating to write but on the flip side I find them easier to read.


That's in part due to the compiler not yet being the best in type inference, and should get better (as far as explicit type signatures are required).


Python is pretty to look at, but I hate working in white space sensitive languages. If I have to have another argument about tabs vs. spaces I am going to toss my monitor out the frickin’ window.

Also, it makes autoindent in Emacs worse.


Well, tabs versus spaces is not a Python thing, that will bite you in any language eventually. Blame the VT-100 terminal.

Here is the thing about indentation versus curly-braces-and-semi-colons: It boggles me that people find it acceptable to use one mechanism to communicate block structure to the compiler, and a completely different mechanism to communicate block structure to humans, and have no way to automatically check that they have the same semantics. This is a frequent source of bugs, and is entirely preventable. When it comes to the ergonomics of computer-convenient versus human-convenient, humans should win. Therefore, significant white space is clearly preferable simply from the standpoint of eliminating the source of an entire class of bugs.

But the main thing that makes Rust harder to read is all the punctuation noise and short, cryptic keywords. While one friend once said: "A good programmer can write FORTRAN in any language.", I don't feel compelled to help them.

Readability matters.


> It boggles me that people find it acceptable to use one mechanism to communicate block structure to the compiler, and a completely different mechanism to communicate block structure to humans, and have no way to automatically check that they have the same semantics. This is a frequent source of bugs, and is entirely preventable.

Strongly agree. The solution that Rust, Go and other new languages have adopted is shipping a formatting tool to consistently make the semantics of indentation and braces match. I personally can't help but think that this is a worse-is-better solution when compared to significant whitespace, but at least it works. Every Rust CI I am setting up will fail the build if `rustfmt --write-mode=diff` feels like you didn't run rustfmt before committing.

> But the main thing that makes Rust harder to read is all the punctuation noise

Given the decision to favor explicit casts, references and dereferences over implicit ones, this cannot really be helped. In some ways, once you get used to it, it helps readability, because it always communicates what the things being worked on are.

> and short, cryptic keywords.

I agree that this was probably a mistake. Cannot really be helped now, though.

Overall, I think the readability argument against Rust is overstated. Sure, when you are starting out it looks like line noise, especially if compared to python. But it didn't take me more than a week or two before it basically became entirely clear and readable. The radical explicitness of the language helps readability in many ways that make it much better than C++.

Of course, much better than C++ is a low bar to pass.


I think Go shipping a single canonical formatting tool was an inspired decision that eliminates a massive point of contention in software teams. I expect the majority of new languages to ship a canonical format tool in the future.


GCC will now warn about (some cases of) misleading indentation, which is a step forward. And clang format can autoformat based on the brackets, I believe.

I still prefer whitespace to indicate blocks though.


PEP-8 (more than 15 years old) recommend spaces, so unless you are deliberately looking for a fight, the question is settled.

Autoindent is a solution to a problem that doesn't exist in Python in the first place. Having two independent representations for blocks, one for human readers (indent) and one for compilers (braces), leads to nasty bugs when they get out of sync. Autoindent is a tool to keep them in sync. In Python there is a single representation, so nothing can get out of sync.


But the tooling for editing the code has no support for indenting blocks as trivially as adding braces. Sure, you just run clang-format or such on the block/file, and get all the visual stuff sorted out.


What editor does not support indenting a block? In most editors I know you select the block and hit tab, or shift-tab to outdent.


The difference is that I can add braces in the middle of multiple lines, just need to get my changes to match up, and then I can tell it to reformat the changed section/the whole file. For block indenting, I have to select each block I want to operate on before issuing the block indent command. Braces let me skip the selecting, requiring the same cursor movement but allowing batch insertion of selection begin/end markers, in a sense.


Or reformat the entire file according to global formatting styles, like IntelliJ.


Wait, let me get under your window...

> If I have to have another argument about tabs vs. spaces I am going to toss my monitor out the frickin’ window.

Clearly the correct answer is spaces. /s

Seriously though, I like python because not only is it pretty, it's also concise. While it's not perfect, a lot of time has been spent on language features to make them easily comprehendable.

The lesson for me from python is that UX is important, even in programming languages.


>Python is pretty to look at

Python is ugly and inconsistent as hell due to lack of methods (no maps or reduce in collections for example), indentation, lack of expressions (nearly everything is a statement) and one statement lambdas.

Though rust is beyond good and evil indeed, I really don't get this obsession with brackets and C-like abominations like &*staff. Ada or SML are doing a much better job.


> I hate working in white space sensitive languages.

I think it's funny how people still have issues with this in 2018.


There is no such thing as white space insensitive language.


Fortran IV came close. You could put spaces in the middle of identifiers, keywords, and numbers, and the compiler ignored them. The language did not require spaces as separators anywhere. Spaces were only significant in Hollerith constants (what we'd call string literals today) and in columns 1-6. Columns 1-6 were reserved for line numbers, comment signifiers, and continuation marks.


Indeed, the classic resulting bug was the do loop with a typo. Instead of comma the program had a period. So this

   DO I = 1.100
was interpreted as assignment

   DOI = 1.1

Though contrary to urban legend it did not result in the loss of any rockets.

   http://catless.ncl.ac.uk/Risks/9.54.html#subj1


Aside from strings, isn’t C white space insensitive?


    intmain()
    {
        r etu rn0;
    }


The tokenizer is. `ab` is different from `a b`.


I had a play with rust at the start of the year while I was evaluating if it would be good for the api backend for my new website. I was using rocket as a framework. The language itself seemed quite ready for use and the book was very helpful but I found all the libraries I needed were half finished and didn't have the features I needed or if they did they had docs that assume you will read the source code and work most of it out yourself. I spent ages trying to work out how to set up postgres with it and got stuck on stuff about connection pools and multithreading.

I ended up just using rails in api mode which is a shame because it chews up the limited memory on my server.

Most of these issues would go away if I was a rust pro and I could just write my own libraries and read the source but it really didn't feel like rust was helping me become productive fast like ruby did.


Ruby is also a dynamically type, interpreted language with a GIL, that's much older than Rust. You're sacrificing a lot in terms of speed and correctness up front to get something that's easier to jump into.

Rust crates should have documentation though. Rust has great tooling around writing docs in comments and generating the documentation from those. Rust is also statically typed, which makes it easier to reason about what a function does without the docs. In fact, lifetimes give you even more information about the relationship between inputs and outputs than a normal statically typed language.


I have never felt a typed language slows me down. In a dynamic language you still have to mentally understand what the type of a function is. You can't just throw any data in to it and have it work.


> In a dynamic language you still have to mentally understand what the type of a function is. You can't just throw any data in to it and have it work.

JavaScript would like a word with you.


If you could just throw any data into JavaScript functions and have it work, we wouldn't need TypeScript.


The poster is poking fun of the fact that you can partially apply or over apply a JavaScript function and it will still run.


One often doesn’t need TypeScript. TS solves some classes of problems that would otherwise become crippling in projects of certain sizes and of certain levels of complexity, but, by design, JavaScript tends to happily let you throw any data into functions and have it work (by some definition of “work”).


If you define work as not throwing an error. You can't just put anything in to a function and have it return a useful result. Thats why typed language programs like haskell programs often define datatypes that are just an Int because user_id is not the same kind of data as product_id even if they are just an int.


Are you?

Every app I've ever written that talks to postgres spends way more time...waiting on postgres than doing anything else.

It's like the joke about getting a faster processor so you're 99% idle instead of 95% idle.


I always found it easier to improve the time waiting for postgres by tuning critical queries than to track down runaway memory usage and tune garbage collection. I also felt like I spent a lot of my wall clock time during active development waiting for apps to start up and run tests or whatever. There are best practices which speak to most of this, but they were hard won.


But that doesn't come for free with Rust. You still have optimize the DB. And then does it really matter which language you use, since the DB is still going consume most of the time generating a web page anyway, right?


My point was that I found the database to be the easier bottleneck to optimize. The other bottlenecks I mentioned, which I found more difficult to optimize - memory usage, GC, and startup time - are things for which Rust has a good story.


You should really be memcaching the database aggressively. I got it to the point that PHP was taking more time than the database for most pages because most pages DON'T need to be updated that frequently.


Seems like Elixir + Phoenix would be a better alternative over rails for you


Maybe. I also tried Haskell and Yesod but had the same issues. It seems the size of the userbase for a language/framework massively impacts how fast I can do things. With haskell I was posting multiple questions on stack overflow every day but with ruby I find almost everything I need already answered.


I imagine the learning curve is a lot more manageable when you have an office full of full time Rust developers. If you’re on your own you become painfully aware of how often you need to solicit help, and the time it takes to familiarize someone else with your problem over chat or forum post really eats away at one’s motivation.


Well the Rust community is super welcoming, and the meetups have been really positive. They even have the #rust-beginners channel. :)

I find Rust to be fairly easy to reason about. The compiler has awesome messages, and even links you to your error type with more information. I also HIGHLY recommend reading the O'Reilly book AND the official Rust book (the free one) if you feel like you're "just not getting it".

Rust is a language that rewards understanding, and stops you from making mistakes when you don't know how things are actually working. This is a revolutionary plus. At the end of the day, Rust's rules are what other languages enforce through convention and the school of hard knocks.

After all, is that not the point of computing? To have the computer check things for you that a human is prone to error on?


> Well the Rust community is super welcoming, and the meetups have been really positive.

For sure. The Rust community takes the cake when it comes to owning criticism, wanting to make things better (as opposed to excusing issues), and self-organizing to affect change (e.g., the working groups). I like Go and its community is well above average, but it stands to learn from Rust's community IMHO.

> the meetups have been really positive. They even have the #rust-beginners channel. :)

I know, but a slack/irc/email/etc channel is a really poor substitute for having humans in a room who already have context about the problem you're trying to solve.

> I find Rust to be fairly easy to reason about. The compiler has awesome messages, and even links you to your error type with more information. I also HIGHLY recommend reading the O'Reilly book AND the official Rust book (the free one) if you feel like you're "just not getting it".

Hard to make heads or tails of this without knowing what you're comparing it to. I do agree that Rust does a fantastic job (via its error messages, documentation, books, etc) at addressing the hard problem of dealing with a compiler that pedantically enforces not-very-intuitive invariants, and I respect Rust for believing that those invariants are worth the trouble. I think they _are_ for lots of applications, but I think Rust needs to do quite a lot on the learnability/intuitability front before the economics justify using Rust for general purpose application development. For the time being, for most applications, it's just so much _cheaper_ to use something like Go in the general case.


> "can we have speed, correctness, and expressiveness in one language?"

Didn't ocaml already answer that question? Since ocaml hasn't dominated, it seems something more is required... What has rust got beyond that?


> OCaml bytecode and native code programs can be written in a multithreaded style, with preemptive context switching. However, because the garbage collector of the INRIA OCaml system (which is the only currently available full implementation of the language) is not designed for concurrency, symmetric multiprocessing is unsupported.

--https://en.wikipedia.org/wiki/OCaml

Rust has memory-safe concurrency without a GC.


Threads and predictable runtime model. (No GC)


Rust does not have predictable allocations, till it would have custom allocators. Malloc is not better than GC.


You're moving goal posts so far I don't even understand what your point is. Malloc vs GC doesn't matter at all because you can decide to not use it if you don't want to in Rust, C, C++. The vast majority of performance sensitive code avoids dynamic allocation of memory at all costs by either preallocating a large chunk of memory upfront and reusing it or by only using the stack. When no allocations are performed in a time critical section of code it is not affected by other threads making allocations. This is what a predictable runtime model is.

Programming languages like javascript or python always dynamically allocate every single object. When the GC does it's job it has to stop all threads and therefore will stop your time critical code even if you avoid allocating inside it. This is what is commonly understood as an unpredictable runtime model.

What does predictable allocations even mean? Allocation is always predictable, it will happen when you use "new" (Java), "Box::new"(Rust), malloc, etc. The unpredictable aspect is the stop the world pause caused by garbage collection. Your complaint regarding custom allocators doesn't make sense because arena allocators [0] and probably others are available in rust.

[0] https://doc.rust-lang.org/1.1.0/arena/index.html


>The unpredictable aspect is the stop the world pause caused by garbage collection.

As well as malloc pauses on deallocation. The only way of using your memory in realtime apps is preallocation, which often can be done in languages with GC too, it would be just very inconvenient.

At the moment custom allocation support in rust is a joke if you compare it with Ada or C++, and Box is not better than GC in this regard.

>Unstable

Besides it's very inconvenient to use. Does Box/Rc/Arc support this arena allocator, as C++'s smart_pointers do?


Threads are an implementation technique, not a user requirement (at least they shouldn't be).


C++ itself is not just overly complicated. However, in addition to that, C++ promotes object orientation. Design patterns add an additional layer of complexity for new grads to plow through.


A shallow learning curve and cute compiler messages are the least of your problems when doing C++-caliber software.

The 'small, easy language for ignorant developers' niche certainly exists, but it's already taken by Go.

Rust currently provides no benefit over (modern) C++ for the problems where using Rust or C++ makes sense. (Though perhaps Rust will make it easier for layman developers to learn Rust and then transition to C++.)


I... what? Rust is hardly targeting "small, easy language for ignorant developers," and putting it in that camp because it has nice error messages is unreasonable.

I'm even more perplexed by "Rust currently provides no benefit over (modern) C++."

* Rust's "pthreads and mutexes" wrappers prevent data races at compile time, and there's Rayon to compete with things like OpenMP.

* Rust's moves are destructive, guaranteed nothrow, and also checked at compile time.

* Rust's borrow checker is light years ahead of C++'s.

* Rust's type system lends itself to far simpler generic code, with trait-based generics and sum types instead of concepts and std::variant.

* Rust's iterators are much better than C++'s, to the point that Ranges is one of the most highly-anticipated additions to C++.

All of these are things C++ is actively trying to improve, so clearly at least the committee agrees they're worthwhile features.


Interesting! I don’t know how modern C++ deals with multi threading and shared memory etc.? Care to fill us in on the state of the art and how it’s as good as rust?


State of the art is pthreads and mutexes. The C++ and Rust wrappers for them are roughly equivalent.

Rust has some nice features for handling ownership semantics, but they are not significantly better than those in C++.

Meanwhile, Rust still lacks a normal exception handling story. Exception handling is absolutely necessary in 2018 for building real software systems.

(And even though Rust claims that errors are nicely dichotomized into "recoverable" and "not recoverable" camps, this is simply not true in the real world. There are obvious counterexamples that don't fit into this dichotomy.)


Haven't spent that much time with rust, but so far Result<> has sufficed for all my exception-needs; it's not clear to me what the practical difference is between exceptions and result<>, that would be relevant to implementing real software systems?

As I understand it, the primary usage of both is to report, and handle, errors. Rust splits it as panic! and Result<>, where panic! is naturally left for logic errors (ie states the program should never reach, regardless of circumstance; maintaining invariants), and Result<> is for everything else.

Exceptions do the same, but you can catch the broken-invariant case as well? I'm not sure how often you want to recover from such a state though.

Another aspect is retrieving the stack-trace, which iirc doesn’t exist in a normal result-type, but error-chain! magically handles it for my case (never looked into how, or at what cost)

Otherwise, the other major difference is that rust enforces that you explicitly handle all result types, making it part of the API contract, while most languages, with unchecked exceptions, leave it as a new runtime error to be found after updating your libraries. Java gives you checked exceptions, but in a much more syntax-unpleasant fashion (but thats always the case with java).

As far as I'm aware, Result<> seems to me a much cleaner solution than exceptions for the same use-case. A bit of concern for API updating, since the errors are part of the API so its more difficult, but at the same time, I'd rather update the library and fix the codebase, than update and wonder if a new Exception exists (or perhaps, always existed? Is there any way to find out the list of possible exceptions in C++, without reading the function, and all the code it depends on?).

The primary unpleasantness is that a single use of Result<> infects the entire callgraph until its handled, but thats true with exceptions as well. I'm not too happy about async/await for the same reason

Of course, part of the reason I'm interested in using rust as my hobby-language is because I'm absolutely sick of runtime errors and writing worthless tests in python, so maybe there's an appeal thats missing for me


> I'm not sure how often you want to recover from such a state though.

Pretty much always in real systems software.

Imagine a multithreaded server that handles HTTP requests. A catastrophic invariant failure when handling one requests shouldn't bring down the whole server.

Or imagine an application that calls into a money transaction routine. (This routine can itself call other routines, and so on for 12 stack frames deep.) A catastrophic failure in sending money shouldn't bring down the whole app, it should show a clean "money transfer failed, please try again" message.


When I'm talking about invariants, I mean something much more fundamental than a web-request failing. It's not a necessarily invalid state (and I'm not sure ever should be for any well-behaved program). It would be invalid if you've explicitly decided not to handle the scenario, but at least in Rust (and assuming the function properly returns Result<>), you can't forget to not handle it.

Essentially where you'd have asserts() in C. eg Your in-place sort function is meant to maintain a sorted list for all elements traversed so far: you add a panic check to guarantee this. It fails; the invariant is broken, and there's no recovering from such a state (your sort is not sorting! you're going to add a handler for this..?).

A web-request failing is a simple, normal, expected failure (hence the Result<> type). Adding 1+1 and getting 3 is a broken invariant, and there's no coming back from it. Again, you can (probably) catch it in Java since it throws exceptions on anything and everything... but why would you want to? If you take its to its conclusion, you're not trusting any aspect of the language anymore: you'll have to check every bit of code for arbitrary outcomes.

It seems to me similar to javascript allowing you to basically pass in anything to everything and get ...some... output, but its an extremely bug-prone methodology.

panic! is, afaik, intended for those situations where it should bring down the whole application (before you start adding $3 to person A, but subtracting $2 from person B); primarily to catch programmer errors, not execution errors. Errors that can be recovered from are Result<>, and the Result<> type forces you to handle all possible outcomes (which the caller might decide is a panic!). A failed web-request is most certainly a Result<> in this model, not a panic!.


That's why you would return a Result from all those and handle any failures that way. The Result type is meant to be used any time an operation could fail.


Do you use only the O'Reilly book? Or do some grads go and buy a few others?


We buy the book for them because we feel it's the best text out there, and they can get the 'Rust Book' for free on Rust's website, so that's two resources for them, plus being able to ask our already ramped up engineers questions.


The failures of Rust are the same failures of C++. Leaky abstractions making it impossible to separate representation details, making the abstraction consume a disproportionate mental load.

Given that Rust doesn't actually solve any of the actual problems C++ programmers have, there is no motivation to switch.


Actual problems like:

- sending dangling references to thread functions. Lambdas with automatic reference capture creating threads from inside functions that exit are terrible here.

- returning a pointer or reference to an invalidated iterator

- returning a pointer or reference to the contents of a temporary

Yes indeed, C++ programmers never actually have these problems, they are purely imaginary. /sarc


Yeah, I don't think there is a professional C++ developer who has any of these problems. It's called static analysis... welcome to a decade ago. Why on earth would an organisation move their codebase to Rust when they can just run Clang? Which they should be doing anyway.....


Unfortunately a lot of browser's CVEs tell a different story.

> Why on earth would an organisation move their codebase to Rust when they can just run Clang? Well, you can ask C++ professional at Mozilla.


In my experience, even modern C++ code and cutting-edge static analyzers still have a lot more holes than Rust when it comes to borrowing and lifetimes. Unsound code like this (which in Rust is the most basic form of lifetime error) still manages to slip past the CppCoreGuidelines static analyzer that Microsoft has been developing for years, which includes "lifetime checking":

    #include <iostream>
    #include <string>
    #include <string_view>

    int main() {
      std::string s = "Hellooooooooooooooo ";
      std::string_view sv = s + "World\n";
      std::cout << sv;
    }
C++ types simply don't contain the information needed to do Rust-style lifetime analysis. C++ static analyzers have to hard-code this knowledge themselves about every library type (will never be complete for every library in existence), use heuristics (will always have some false positives and false negatives), or rely on whole-program analysis of function bodies rather than signatures/types (runs into incomputability problems, and validity ends up depending on things the analyzer can't know, like which version of a dynamic librariy ends up linked at run time).


Rust is based on ADTs, typeclasses, and type parameters. C++s toolkit for abstraction is templates and OOP. They're completely different, and it sounds like you're just trolling anyway.


C++ has ADTs from C++17 and will have typeclasses from C++20. Templates with type traits are effectively a superclass of type parameters anyway.


C++'s ADTs are std::variant, which is horrific.

C++'s type classes are concepts, which are hardly more than syntactic sugar over SFINAE.

Neither can really compare to Rust's enums or traits.


Templates generate bad error messages because they are duck-typed. Rust is better at this.




Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: