Live data from Hacker News

How I went about learning Rust

eli.thegreenplace.net

201–210 of 303 posts

Re: How I went about learning Rust

#201

Earlier quoted context omitted.

Rust actually supports most OOP features, with the main exception of implementation inheritance. And implementation inheritance is a nasty footgun in large-scale software systems (search around for: "fragile base class problem"), in a way that just doesn't apply to simple composition and pure interfaces (traits). So it's hard to fault Rust for including the latter and not the former.

For me it was the web-of-pointers strategy I had to unlearn. A child object keeping a pointer to its parent is misery in Rust. It forces you to either make the child completely independent or really prove the parent will be around until the child disappears. 90% of the time this is dumb overhead, but 10% of the time it found a bug in some edge case, so I learned to appreciate it as a tough teacher, and my designs got…

> designs got better for it.

What is better about them?

Re: How I went about learning Rust

#202

Earlier quoted context omitted.

I'm self-publishing "Rust From the Ground Up" which takes this approach: each chapter rewrites a classic Unix utility (head, cat, wc, ...) from the original BSD C source into Rust. I find for systems programming it's easier to understand how things work in C, and then teach the idiomatic way of doing it in Rust. C is pretty easy to follow along in "read-only" mode with some explanations. https://rftgu.rs/

Interesting, seems similar to the book Command Line Rust which also teaches you by reimplementing Unix commands, any thoughts on the differences?

Yes I saw that... I released mine first but I'm publishing it a chapter at a time and mine is about half done. I haven't read the O'Reilly one because I don't want to inadvertently copy anything or be influenced by it. I think the main difference between my book and this one is that I go through the original BSD source and translate it into idiomatic Rust. I also teach how to work with the borrow checker without resorting to copy/clone or reference counting which I think is unique. And I don't use lifetimes anywhere in the book - they're an advanced topic that really puts off new Rust programmers and aren't needed in most cases.

Re: How I went about learning Rust

#203
post #88
post #3

I have been thinking to myself whether I should pick up Go or Rust as a new language this year. Coming from a NodeJS background, Rust looks a tad more complicated but it looks cooler. There are also more job listings looking for Golang than Rust which makes me wonder if Golang might be a more rewarding investment? What would be a good use case of Rust than Golang cannot do given its extra complexity and potentially l…

If you want to optimize your learning experience, then learn Go first. Rust has a very steep learning curve, whereas you can pick up Go very very quickly. I learned Go by reading The Go Programming Language. It's a bit old, but a very good book nonetheless.

I second this. I'm a huge Rust fan, and not really a Go fan, but if you're thinking about leaning both, it will be much faster to learn Go first. Spend a couple weeks on that, and then you'll have another data point to compare while you learn Rust. (Go also distinguishes between pointers and values, which will be a helpful concept to have under your belt when you start Rust.)

Re: How I went about learning Rust

#204
post #145
post #62

Earlier quoted context omitted.

> Rust is a better c++ The Rust language is a far better C++. In practice, the compile time and binary size of Rust are out of control, which makes Rust far from being a slam dunk over C++. Crossing my fingers this will change!

As of Rust 1.62, compilation time is no longer a valid criticism. Things have improved so much in the past 2-3 versions, it's no longer slower than C++. Sorry!

There are a few things to make things slow still. Try macros generating async code. That can go out of control and is a common case in tests.

Re: How I went about learning Rust

#205
post #100
post #14

Earlier quoted context omitted.

Rust is the more elegant and powerful language. Creating a new language and repeating the "billion dollar mistake" by including null (sailing under the brand name "nil" in Go) is just crazy. Error handling is another strange thing in Go. And generics have been only introduced recently, but there is hardly any support for libraries in it (now). While Go is definitely fast enough for most scenarios, it is not the best…

> Creating a new language and repeating the "billion dollar mistake" by including null (sailing under the brand name "nil" in Go) is just crazy. Can you explain? What do I set ‘score’ to when someone hasn’t sat the test yet?

I use Go at my job, and Rust in a few personal projects.

The "typical" Go nil-check would usually look something like this (no idea how code will look, apologies up front):

result, err := someFunction()

if err != nil { ...

It's nice that you're not having to litter your code with try/catch statements, or use a union type with an error value like in other languages, but the downside is that Go only checks to see whether err is used at some point (or makes you replace it with _), and it's possible to accidentally use err in a read-context and skip actually checking the value. Go won't prompt you that the error case is unhandled (in my experience)

In Rust, when you want to return a null-like value (None), you wrap it in Option. To the compiler, Option is a completely separate type, and it will not allow you to use it anywhere the interior type is expected until the option is unwrapped and the possible null value is handled. You'd do that like this:

var result = some_function()

match result {

  Some(x) => handle_value(x),

  None => handle_null(),
}

The compiler forces you to unwrap result into its two possible underlying types (any possible or None), and handle each case, which prevents an accidental null value being passed to handle_value. Trying to pass result directly into handle_value would give you a type check error, since it's expecting a but is passed an Option. The compiler will also give you an error if you try to only handle the Some(x) path without providing a case for None as well, so you can't just accidentally forget to handle the null case.

(For completeness, you can also just do result.unwrap() to get the inner value and panic if it is None, which can be useful in some cases like when you know it will always be filled, and you want to fully terminate if it somehow isn't).

So in your case (assuming this is in the context of a video game), you'd make score an Option for example, then unwrap it when you needed the actual value. Generally speaking, I'd make the score returned from a saved game loading function be Option and make the actual score for the current session just an i32, then the function that handles loading a game save into the current session would handle the Option from the save file (defaulting to 0 when this is None), and we could assume that the score would be set by the time the game session is running so we don't have to constantly unwrap it within the game logic itself.

Re: How I went about learning Rust

#206
post #194

Earlier quoted context omitted.

6MB is quite large. Makes me question if you were even building in release mode. You may want to see https://github.com/johnthagen/min-sized-rust It's not difficult to get binaries down into the 50KB range. And for embedded applications, less than 10KB is totally possible.

Yes I tried all those 'minimize rust' approaches including the above one. they worked fine if you're statically link to its stdlib. but if you have a few complex rust binaries, static link for each of them is not going to help on the overall combined size. I did use a released library and build everything for release(per those minimize projects), I can easily cut a small program from 3M to 290KB but again, it is eith…

Oh so your problem is that when attempting to dynamically link to the standard library, you're missing out on the dead code elimination you'd get when statically linking. Rust doesn't have a stable ABI anyways, so you can't really share the standard library between programs unless you're really careful.

Re: How I went about learning Rust

#207
post #3

I have been thinking to myself whether I should pick up Go or Rust as a new language this year. Coming from a NodeJS background, Rust looks a tad more complicated but it looks cooler. There are also more job listings looking for Golang than Rust which makes me wonder if Golang might be a more rewarding investment? What would be a good use case of Rust than Golang cannot do given its extra complexity and potentially l…

I have no experience with Rust myself and a good 2-3 years with Go, so my opinion here is biased but: I think Go is more suitable for general all-purpose programming, whereas Rust is more specialized; I'd pick the latter if you need to do high-quality, close-to-the-metal software, and Go for more generic software, taking the same spot that NodeJS did for you. That said, Go isn't a very "convenient" language; there's…

You might look into your database's support for JSON columns. Sometimes you can even make indices for expressions on them

Re: How I went about learning Rust

#208
post #200

Earlier quoted context omitted.

>If it's a single score, I'd still want to use null / int. In your example, you still have to manually check if there's a value every time, but this is not compiler-enforced. Should you forget, you will get a runtime crash at some point (likely in production at a critical time) with some kind of arithmetic error. This wouldn't be possible with a simple sum type. Also, a sum type with units of Score(Int) and NoScore w…

The compiler would enforce Number-ness every time I try and run a function that takes a number, right? Wouldn’t I still have to check for NoScore? > a sum type with units of Score(Int) and NoScore won't allow assignments of any other "null" instances. I get this part - I wouldn’t be able to assign ‘NewBornBaby’ (my name null) to ‘NoScore’ (my score null)

>Wouldn’t I still have to check for NoScore?

That's right, and the compiler will reject programs where you don't do this. It's a set of safety rails for your code. You pay a dev-/compile-time cost in exchange for your programs not exploding at runtime.

Re: How I went about learning Rust

#209

Earlier quoted context omitted.

I get the sentiment, but like to nuance it a bit. The compile time story of rust and C++ is comparable, if you use it the same way. If you use deep include hierarchies and no precompiled headers, if you start using template heavy code like boost, or if you do code generation, the C++ compile times will quickly spiral out of control. Rust does not have the include problem, but the specialization/templating idea is sha…

Rust has a stable ABI actually, it's called the C ABI. But since most Rust crates do rely on monomorphized generic code in many ways, it's just not possible to share binary artifacts in the first place. (The situation is similar for "header only" libraries in C++.) If you're writing a library that truly does not involve generic code, it makes total sense to expose it via a pure C interface anyway so that languages ot…

C ABI is very well supported indeed. After commiting some contortions to avoid varargs, I found out Rust does actually cover them.

But it's still something different than a real rust ABI. Basic things like pushing a string or an enum to a client will hurt. Providing a rust library without source is not an option for now.

Re: How I went about learning Rust

#210
post #100
post #14

Earlier quoted context omitted.

Rust is the more elegant and powerful language. Creating a new language and repeating the "billion dollar mistake" by including null (sailing under the brand name "nil" in Go) is just crazy. Error handling is another strange thing in Go. And generics have been only introduced recently, but there is hardly any support for libraries in it (now). While Go is definitely fast enough for most scenarios, it is not the best…

> Creating a new language and repeating the "billion dollar mistake" by including null (sailing under the brand name "nil" in Go) is just crazy. Can you explain? What do I set ‘score’ to when someone hasn’t sat the test yet?

You can still use a null, however the point being made here is that null was failed to be included at type level.

See these for reference

* https://kotlinlang.org/docs/null-safety.html

* https://dart.dev/null-safety

* https://docs.microsoft.com/en-us/dotnet/csharp/nullable-refe...

An orthogonal approach would be using a data type such as Maybe or Option, but ergonomics depends on language.

Post reply on HN