Live data from Hacker News

Flattening Rust’s learning curve

corrode.dev

101–110 of 405 posts

Re: Flattening Rust’s learning curve

#101

Earlier quoted context omitted.

I have taken the time to learn rust and you're absolutely right. It's a very complex, design-by-committee language. It has brilliant tooling, and is still much less complex than it's design-by-committee competitor C++, but it will never be easy to learn.

> It's a very complex I find it relatively simple. Much simpler than C++ (obviously). For someone who can write C++ and has some experience wth OCaml/Haskell/F#, it's not a hard language.

Sure, C++ has a more complex spec, nobody can argue against that.

Complex is the wrong word. Baffling is a better word. Or counterintuitive, or cumbersome. If “easy enough for someone with experience in C++, OCaml, Haskell, and F#” were the same thing as “not hard” then I don’t think this debate would come up so frequently.

Re: Flattening Rust’s learning curve

#102

Rust is wonderful but humbling! It has a built in coach: the borrow checker! Borrow checker wouldn't get off my damn case - errors after errors - so I gave in. I allowed it to teach me - compile error by compile error - the proper way to do a threadsafe shared-memory ringbuffer. I was convinced I knew. I didn't. C and C++ lack ownership semantics so their compilers can't coach you. Everyone should learn Rust. You nev…

> Everyone should learn Rust.

I know this feels like a positive vibe post and I don’t want to yuck anyone’s yum, but speaking for myself when someone tells me “everyone should” do anything, alarm bells sound off in my mind, especially when it comes to programming languages.

Re: Flattening Rust’s learning curve

#103

Write a CHIP8 emulator! Bonus: do it with no heap allocation. This actually makes it easier because you basically don’t deal with lifetimes. You just have a state object that you pass to your input system, then your guest cpu system, then your renderer, and repeat. And I mean… look just how incredibly well a match expression works for opcode handling: https://github.com/ablakey/chip8/blob/15ce094a1d9de314862abb... My…

I’ve found emulators to be a pretty poor first project for rust specifically for the reasons you alluded to: That you need to know to write it without heap allocation (or other hoop jumping so long as you avoid juggling lifetimes) when so much literature and example emulator code doesn’t do this is a recipe for a bad experience. Ask me how I know.

If you’re going to write an emulator in this style, why even use an imperative language when something like Haskell is designed for this sort of thing?

Re: Flattening Rust’s learning curve

#104
post #6

Earlier quoted context omitted.

For people who don't get the reference, this might be referring to the notoriously gnarly task of implementing a doubly-linked lists in Rust [1] It is doable, just not as easy as in other languages because a production-grade linked-list is unsafe because Rust's ownership model fundamentally conflicts with the doubly-linked structure. Each node in a doubly-linked list needs to point to both its next and previous nodes…

Apologies since I have not taken the time to learn rust yet, but I've written a lot of modern C++. Is the ownership model kind of like std::unique_ptr and std::move, and `Rc >` the same idea as `std::shared_ptr`? But less idiomatic? Or do I have the wrong idea?

Not really, because Rust enforces a "many readers or one writer" invariant on everything that has no C++ equivalent. That invariant is precisely what makes the doubly-linked list case hard (because every interior node in the list would be readable from two places, which means it can never be written to).

Re: Flattening Rust’s learning curve

#105

Regarding the first example, the longest() function, why couldn't the compiler figure it out itself? What is the design flaw?

You’re passing in two references and returning a reference. The compiler knows the returned reference must be tied to one of the incoming references (since you cannot return a reference to something created within the function, and all inputs are references, the output must therefore be referencing the input). But the compiler can’t know which reference the result comes from unless you tell it. Theoretically it could…

> Theoretically it could tell by introspecting the function body, but the compiler only works on signatures

Note that this is an intentional choice rather than a limitation, because if the compiler analyzed the function body to determine lifetimes of parameters and return values, then changing the body of a function could be a non-obvious breaking API change. If lifetimes are only dependent on the signature, then its explicit what promises you are or are not making to callers of a function about object lifetimes, and changing those promises must be done intentionally by changing the signature rather than implicitly.

Re: Flattening Rust’s learning curve

#106
post #21

Earlier quoted context omitted.

Rust still needs a way out of that mess. It's conceptually possible to have compile time checking for this. Think of RefCell/Weak and .upgrade() and .borrow() being checked at compile time. I've discussed this with some of the Rust devs. The trouble is traits. You'd need to know if a trait function could borrow one of its parameters, or something referenced by one of its parameters. This requires analysis that can't…

> Rust still needs a way out of that mess. In practice, it really doesn't. The difficulty of implementing doubly linked lists has not stopped people from productively writing millions of lines of Rust in the real world. Most programmers spend less than 0.1% of their time reimplementing linked data structures; rust is pretty useful for the other 99.9%.

Doubly linked lists are rare, but backlinks to the owner are often needed. It's the same problem, mostly.

Re: Flattening Rust’s learning curve

#109

Regarding the first example, the longest() function, why couldn't the compiler figure it out itself? What is the design flaw?

It's a design choice. To make a compiler automatically handle all of the cases like that, you will need to do an extensive static analysis, which would make compiling take forever.

Would be nice if an IDE can autofix it.

Maybe autofix as we type, or autofix when it save the document / advance to next line.

Re: Flattening Rust’s learning curve

#110

Regarding the first example, the longest() function, why couldn't the compiler figure it out itself? What is the design flaw?

Compiler can figure that out, but the thing is compiler needs also to understand lifetimes at the site where this function is called. In general case compiler will not look into the code of a called function to see what it does, compiler relies on a function declaration.

That `longest` if defined without explicit lifetimes treated like a lifetime of a return value is the same as of the first argument. It is a rule "lifetime elision", which allows to not write lifetimes explicitly in most cases.

But `longest` can return a second reference also. With added lifetimes the header of the function says exactly that: the lifetime of a return value is a minimum of lifetimes of arguments. Not the lifetime of the first one.

Post reply on HN