[HN Gopher] Effective Rust (2024)
___________________________________________________________________
Effective Rust (2024)
Author : ibobev
Score : 127 points
Date : 2025-03-01 08:59 UTC (1 days ago)
(HTM) web link (www.lurklurk.org)
(TXT) w3m dump (www.lurklurk.org)
| thurn wrote:
| Kind of surprised that this book could be published by O'Reilly
| and also freely available online? Seems unusually generous.
| darthrupert wrote:
| Possibly a sign of confidence. After browsing this for a few
| minutes, I'm very convinced of its quality and will probably
| buy it.
|
| Wouldn't have happened with a book with just sample pages.
| jjallen wrote:
| Why buy it if it's completely free which is implied by your
| post?
| kshri24 wrote:
| To support the author. And as a way of saying thank you.
| dcminter wrote:
| Because we all know what happens if we're not the customer.
|
| I have this; I bought it because I want to reward the
| author for producing a quality work, and because I want to
| encourage the publishers to produce other works that would
| appeal to me.
|
| I also happen to like physical texts so I bought the
| paperback but I have this and the digital edition. The
| latter is convenient for when I am travelling and
| appropriately formatted for an eReader (not just the raw
| html from these pages).
| smodo wrote:
| The book isn't free, its contents are published online by
| the author. Yes, nitpicking. But (1) I like a well
| formatted epub and (2) the author/publisher still hold
| copyright.
| darthrupert wrote:
| Because I have written a book and thus know how much work
| it is to write even a mediocre one.
|
| Also as a way to increase my motivation to read it.
|
| Plus I have money. This book costs about as much as a good
| bottle of wine or a bad bottle of whiskey.
| dcminter wrote:
| > Plus I have money. This book costs about as much as a
| good bottle of wine or a bad bottle of whiskey.
|
| Exactly.
|
| A few years ago I did a really aggressive weeding out of
| my bookshelves as things were getting far too cluttered.
| In the process I threw out what must have been - at cover
| price - several thousand pounds worth of IT related
| books.
|
| On the resale market they were all too stale to have any
| value (though I did manage to give a handful away to
| friends). In one way it was a bit painful, but those few
| thousand pounds worth of books has given me a huge
| (financial) return on that investment!
|
| Cheap at the cost of a good bottle of wine ... for the
| foundations of a career!
| vaylian wrote:
| Because the people want to show appreciation for the good
| work the author has done?
| codr7 wrote:
| True for digital copies, I've never yet bought one of
| those.
|
| I have no trouble paying for physical books though.
| akkad33 wrote:
| I want to read on Kindle or own the book.
| WD-42 wrote:
| The last 2 books I've bought (ostep and nand2tetris) are
| available online. Hard copies are nice and personally
| seeing it on my desk gives more more motivation to finish
| them.
| johnisgood wrote:
| Rust is so full of symbol soup. <'_>)
|
| is a very simple one, but there are ones with ~7 consecutive
| symbols, and there are a lot of symbols all over Rust code.
|
| How come it is in demand?
|
| Cool book though.
| stouset wrote:
| Symbols are just other letters in the alphabet. Something like
| <'_> is as natural for me to read at this point as any of the
| other words in this sentence.
|
| Math is also symbol soup. But those symbols mean things and
| they've usually been designed to compose nicely. Mathematicians
| using symbols--just like writers using alphabets--are able to
| use those symbols to concisely and precisely convey complicated
| concepts to one another.
|
| I guess my point is that symbols shouldn't be looked at as
| inherently a positive or negative thing. Are they clear and
| unambiguous in their use? Do they map clearly onto coherent
| concepts? When you need to compose them, is it straightforward
| and obvious to do so?
| Etheryte wrote:
| I think many programming languages could benefit if we had an
| easy way to have both custom symbols and a convenient way to
| input them without extra friction. Take APL for example, once
| you know the language it's incredibly expressive, but the
| overhead to typing it is so strong that many use custom
| keyboards/caps.
| ufo wrote:
| I wish compose keys were more prevalent. There's something
| nice about typing -> and getting -
| bombela wrote:
| To be fair the basic ASCII keyboard is also default in
| US/Britain. And most people assume that's all they get.
|
| I have always used the "international" version of the US
| English keyboard on Linux.
|
| And I can enter all common symbols pressing altgr or altgr-
| shift. I also use right Ctrl as a compose key fore more. I
| would be hard pressed remembering what combo to press,
| after years it's just muscle memory.
|
| But how do you find out what layout and what compose key
| does what? Good luck. It's as documented as gesture and
| hidden menus on iOS and MacOS. sigh.
| jonahx wrote:
| Uiua (https://www.uiua.org/), broadly in the APL lineage,
| solves this problem nicely.
|
| Like APL, it has a set of well-chosen symbols, but each
| symbol has an english name you can type just as you would a
| function name in another language, and it's automatically
| converted to the symbol when you run it.
| johnisgood wrote:
| Well, I wish I could find the ones I have seen in the wild.
|
| Perhaps HRTBs and Fn traits, or double turbofish generics. I
| really cannot remember sadly.
| stouset wrote:
| Even something like foo::<'_, [T]>() is just not that hard
| to follow. Again, the symbols involved all compose nicely
| and are unambiguous. And frankly, you just don't need
| something like that all that often (and when you do, there
| are usually other alternatives if you're really put off by
| the symbols.
| johnisgood wrote:
| Someone mentioned the use of ")?)?" (in terms of error
| handling), I am quite put off by this, too. :P
|
| Anyways, I will try to look for the code, it is somewhere
| in my comment history but I have left way too many
| comments, so no promises.
| stouset wrote:
| I would one million percent rather type (and read)
| foo(bar()?)?
|
| over something like if a, err := bar()
| { return nil, err } if
| b, err := foo() { return nil, err }
|
| But also even better is just let a =
| bar()?; let b = foo()?;
| johnisgood wrote:
| I prefer ("if a, err := bar() {"), the same things you
| said applies here, too. I write a lot of Go and I can
| glance through it quickly, there is no cognitive overhead
| for me.
|
| Edit: actually, it was someone else who said this: "Human
| brain has a funny way of learning how to turn off the
| noise and focus on what really matters.".
| stouset wrote:
| The difference is, there is no room for bugs with ?.
| Zero. None.
|
| I have fixed (and frankly, caused) many bugs in golang
| code where people's brains "turned off the noise" and
| filtered out the copypasta'd error handling, which
| overwrote the wrong variable name or didn't actually
| bubble up the error or actually had subtly wrong logic in
| the conditional part which was obscured by the noise.
|
| Frankly, learning to ignore that 80% of your code is
| redundant noise feels to me like a symptom of Stockholm
| syndrome more than anything else.
|
| One symbol to replace three lines of identical
| boilerplate is no less explicit and dramatically clearer.
| jcelerier wrote:
| > Math is also symbol soup. But those symbols mean things and
| they've usually been designed to compose nicely.
| Mathematicians using symbols--just like writers using
| alphabets--are able to use those symbols to concisely and
| precisely convey complicated concepts to one another.
|
| I just don't understand why one may take maths of all things
| as a positive example of something readable, when it's widely
| known to be utterly inscrutable to most humans on earth and
| even so many papers have differing conventions, using the
| same symbol for sometimes widely different or sometimes
| barely different things
| pharrington wrote:
| _Literally_ every language is inscrutable to most humans on
| Earth. But they all work fairly well for those in the club
| that know them!
| DistractionRect wrote:
| It's more batteries included and the packaging ecosystem story
| is better than alternatives. Certain safety guarantees are a
| nice to have.
|
| If you just want a better c/c++ afaik that's zig, but I have no
| experience with it
| no_wizard wrote:
| An aside question I have is what's the best beginner Rust
| book out there that is up to date?
|
| I been learning Rust off and on and I have a more serious
| need to get up to speed with it but I'm unsure where it's
| best to start in this way
| smodo wrote:
| The Rust Programming Language does a great job imho. It got
| me up to speed by reading it before bed for a month. I'd
| never written C/C++ before, just a lot of Python. It starts
| out really simply by explaining the type system and the
| borrow checker. Take it from there and do a couple of side
| projects, I'd say.
| kshri24 wrote:
| In this order:
|
| 1. The Rust Book (Free) - https://doc.rust-lang.org/book/
|
| 2. Rust by Example (Free) - https://doc.rust-lang.org/rust-
| by-example/
|
| 3. Rust Atomics and Locks - https://marabos.nl/atomics/
|
| 4. Rust in Action - https://www.rustinaction.com/
|
| 5. Rust for Rustaceans - https://rust-for-rustaceans.com/
|
| Also Jon Gjengset's channel is immensely valuable:
| https://www.youtube.com/c/JonGjengset
| crablearner wrote:
| I have a hard copy of Programming Rust by Jim Blandy et
| al would that slot in nicely anywhere here?
| thesuperbigfrog wrote:
| "Programming Rust" by Jim Blandy et al was the book that
| really helped me to understand _why_ many of the design
| decisions behind the implementation of Rust were made.
|
| I found it more approachable than some of the other Rust
| books and highly recommend it as a first Rust book.
| kshri24 wrote:
| Unfortunately, I haven't read Programming Rust. The list
| includes just the books I used to learn Rust. But will
| definitely give Blandy's book a read. Thanks for the
| recommendation!
| akkad33 wrote:
| What do you think about Rust for Rustaceans? I read it
| and there are very niche and useful information there
| about Rust that I didn't see anywhere. It's a solid book
| but for a book about programming there are so few real
| code examples that it can come off dry. I just bought
| Rust atomic and locks and it seems exercise based, so I'm
| excited to finish it. The first chapter seems promising
| timeon wrote:
| As title implies, Rust for Rustaceans is not for those
| that are just starting with the language.
| kshri24 wrote:
| You are right about it not being a beginner friendly
| book. Hence why I placed it lower in the order of books
| to study.
|
| Yeah Rust atomics and locks is essential if you truly
| want to understand low-level concurrency. But you might
| have to also refer to the C++ std::atomics reference [1]
| to get a complete idea. It took me a while to grasp those
| concepts.
|
| [1]: https://en.cppreference.com/w/cpp/atomic/atomic
| codr7 wrote:
| C/C++ are two very different languages.
|
| Zig seems to follow the C tradition, and Rust C++.
| akkad33 wrote:
| Why do people say Rust follows the tradition of C++? Rust
| follows very different design decisions than C++ like a
| different approach to backwards compatibility, it does not
| tack on one feature on top of another, it is memory safe
| etc that are very different from C++. If you are just
| comparing the size of language, there are other complex
| languages out there like D, Ada etc
| worik wrote:
| > Why do people say Rust follows the tradition of C++?
|
| They mean the domain that Rust is in.
|
| Before Rust there was only C or C++ for real time
| programming. C++ was an experiment (wildly successful IMO
| when I left it in 2001) trying to address the
| shortcomings of C. It turned out that too much of
| everything was in C++, long compile times, a manual
| several inches thick, huge executables. Some experiments
| turned out not to be a good idea (exceptions, multiple
| inheritance, inheritance from concrete classes....)
|
| Rust is a successor in that sense. It draws on the
| lessons of C++ and functional programming.
|
| I hope I live long enough to see the next language in
| this sequence that learns form the mistakes of Rust
| (there are a few, and it will take some more years to
| find them all)
| KerrAvon wrote:
| Zig is not yet stable enough to base a long-term project
| around, unless something's changed very recently.
|
| If you really only want a better C/C++, use C++ and amp up
| your use of safer types (or consider D).
| worik wrote:
| > the packaging ecosystem story
|
| I love Rust, I am a devotee and an advocate.
|
| But the packaging system, more importantly the lack of a
| comprehensive system crate, is one of the greatest weaknesses
| of Rust.
|
| A simple programme can pull in hundreds of crates from
| goodness knows where and by Dog knows who, for all sorts of
| uncertainties.
|
| There are work arounds, but they eat up time that could be
| used far more productively
| kshri24 wrote:
| Lifetimes and annotations only look like symbol soup initially
| (when you have little to no experience in Rust). The more
| proficient you become in Rust more you end up ignoring it
| completely. Sort of like ads you see (or don't) in Search.
| Human brain has a funny way of learning how to turn off the
| noise and focus on what really matters.
| gauge_field wrote:
| Rust's design is designed to be more in the mentality of if it
| compiles that it is good enough, leaving less for runtime
| issues to occur unexpected, dictated by type and memory safety.
| So, it requires more type info (unless you use unidiomatic
| unsafe code) and talking with borrow checker. But, once you
| internalize its type system and borrow checker, it pays off if
| you care about compiler driven development (instead of dealing
| with errors in runtime).
| BrouteMinou wrote:
| You become used reading this. Typing it is such a pain; I mean
| real pain like muscle pains.
|
| I developed some muscles I didn't know I had.
| dcminter wrote:
| > How come is it in demand?
|
| It's a curly-brace language with some solid decisions (e.g.
| default immutability) that produces static binaries and without
| a need for a virtual machine, while making some guarantees that
| eliminate a swathe of possible bug types at compile time.
|
| As others note, the symbol soup is something you learn to read
| fluently and isn't worth getting hung up on.
|
| Basically it occupies something of a sweet spot in the
| power/useability/safety space and got a decent PR shove by
| coming out of Mozilla back when they were the cool kids. I like
| it a lot. YMMV.
| booleandilemma wrote:
| What is this constant push in software development to dumb
| everything down to the lowest common denominator?
|
| I don't see it in other fields, at all.
| codr7 wrote:
| I have to say I have no trouble seeing it absolutely
| everywhere.
| worik wrote:
| > dumb everything down to the lowest common denominator
|
| What do you mean?
| airstrike wrote:
| <'_> is one of the most basic symbols in Rust. Reading that is
| almost like reading the letter 'a after just some very modest
| amount of time with the language.
|
| > How come is it in demand?
|
| Because there's a lot more to the language than just those not-
| really-unfamiliar symbols
| jeroenhd wrote:
| I agree that Rust can look pretty weird to an untrained
| developer when lifetimes get involved. But, in Rust's defence,
| I haven't seen any other language write down lifetimes more
| concisely.
|
| The underscore could've been a name if the name mattered, which
| would be required in many languages. Rewriting it to
| <'something>) may help readability (but risks introducing bugs
| later by reusing `something`).
|
| Many C-derived languages are full of symbol soup. A group like
| <?,?>[]) can happen all over Java, for instance. Many of these
| languages have mixes of * and & all over the place, C++ has .
| and -> for some reason, making for some pretty unreadable soup.
| The biggest additions I think Rust added to the mix was ' for
| lifetimes (a concept missing from most languages,
| unfortunately), ! for a macro call (macro invocations in many
| other languages aren't marked at all, leaving the dev to figure
| out if println is a method or a macro), and ? to bubble up
| errors. The last one could've been a keyword (like try in Zig)
| but I'm not sure if it makes the code much more readable that
| way.
|
| If you know other programming languages, the symbols themselves
| fall into place quite quickly. I know what <'_> does in Rust
| for the same reason I know what <T, R> T does in Java, while a
| beginner or someone who hasn't learned past Java 6 may struggle
| to read the code. Out of all the hurdles a beginning Rust
| programmer will face, the symbols are probably your least
| concern.
|
| As for books, the Rust book on the Rust website is kept up to
| date pretty well. There are books for programmers coming from
| various other languages as well.
|
| The language itself hasn't changed much these past few years.
| The standard library gets extended with new features, but a
| book a few years old will teach you Rust just fine.
|
| In many cases, changes to the language have been things like
| "the compiler no longer treats this as broken (because it
| isn't)" and "the compiler no longer requires you to write out
| this long definition because it can figure that stuff out
| itself". I'd recommend running a tool called "clippy" in your
| IDE or on the command line, if you can leverage a modern
| language feature for better legibility, clippy will usually
| suggest it.
| dietr1ch wrote:
| > I agree that Rust can look pretty weird to an untrained
| developer when lifetimes get involved. But, in Rust's
| defence, I haven't seen any other language write down
| lifetimes more concisely.
|
| Can you do a lot better? I don't think so and it wouldn't
| help that much.
|
| The truth is that most of the time we want to rely on some
| inferred lifetime annotations, but will obviously need an
| escape hatch from time to time.
|
| Rust doesn't waste a lot of typing around the annotations,
| but if you were to improve Rust, you'd improve the implicit
| inference, not the syntax for being explicit.
| dbdoskey wrote:
| (not OP) I love rust, bu I just think that using ' for
| lifetime was a huge mistake, and using <> for templates
| (rather than something like []) was a medium mistake.
|
| There is something about how the brain is wired, that using '
| for lifetime, just triggers the wrong immediate response to
| it.
|
| Something like this would look so much nicer IMHO [$_],
| compared to this <'_>.
| dralley wrote:
| I completely disagree that [$_] looks nicer than <'_>.
| thrance wrote:
| Wait til you learn about APL...
|
| Seriously though, I immediately parse it as "generic bounds
| containing the erased lifetime, close parenthesis". It's not a
| big deal.
|
| And of all the critics one might have on Rust (or any other
| programming language), "too much symbols" appear like a weak
| one.
| dhruvrajvanshi wrote:
| > How come it is in demand?
|
| Because it's a complicated language for building extremely low
| level things, when you have no other choice. IMO it's not the
| right tool for high level stuff (even though it does have some
| stuff which higher level languages should probably borrow).
|
| The only other language that directly competes with Rust IMO is
| C++, which is equally full of symbol soup.
| worik wrote:
| > IMO it's not the right tool for high level stuff
|
| I thought that for a long time. But as time passes and I
| spend more time in languages like Typescript (Semi-Type
| Script more accurately) and Swift the more I yearn for Rust.
|
| It is not the right tool for scripting, true.
| gauge_field wrote:
| Yeah I feel that, not the entire language but, many of its
| choices, like error handling, sum types (with exhaustive
| enum matching) especially when writing in python.
| timeon wrote:
| I find it fine for high-level stuff as well. I never get
| complaining about syntax (in any language).
| hardwaregeek wrote:
| Rust's syntax isn't gonna win any awards, but it looks
| sufficiently like C++ to hide that Rust is essentially an ML
| variant with linear types.
| satvikpendem wrote:
| Now try BQN (Advent of Code 2020 Problem 2):
| Split -(([?]-~+`x!)[?]=[?][?])
| input2-' 'Split"*file.Lines "../2020/2.txt" # change string to
| your file location Day2-{
| f-[?]{([?])+|1+|-'}_{-1} # Select the [I]ndex generator
| [F]unction I-{F *BQN" '-' Split [?]} # [I]ndices
| used to determine if the C-{[?]1[?]}
| # [C]haracter appears in the P-{[?][?]}
| # [P]assword either
| Part1-(I[?]~*+'C= P)" # a given number of times
| Part2-(1= *+'C=I[?]P)" # or at one of a pair of indices
| [?]+'#Part1_Part2
| } *Show { Day2 input2}"|2
| musicnarcoman wrote:
| While I am only a Rust novice it seems to me like the "2.2 Item
| 11: Implement the Drop trait for RAII patterns" could use some
| kind of mention of Drop-leaks. I learned about it at
| https://doc.rust-lang.org/nightly/nomicon/leaking.html
| loeg wrote:
| The big foot-gun here is mem::forget rather than Drop itself.
| Although yeah it is pretty surprising that is considered safe.
| vlovich123 wrote:
| It's not that surprising when you consider that "unsafe" only
| concerns itself with memory safety. mem::forget is not unsafe
| from that perspective.
|
| > In the past mem::forget was marked as unsafe as a sort of
| lint against using it, since failing to call a destructor is
| generally not a well-behaved thing to do (though useful for
| some special unsafe code). However this was generally
| determined to be an untenable stance to take: there are many
| ways to fail to call a destructor in safe code. The most
| famous example is creating a cycle of reference-counted
| pointers using interior mutability.
| loeg wrote:
| Yes, thanks, I read the article. Nevertheless, it's still a
| surprising footgun.
| 0x457 wrote:
| What's unsafe about implicitly "leaking" memory?
| loeg wrote:
| Destructors do more than just free memory.
| charlotte-fyi wrote:
| The important note here is that you can't rely on Drop running
| in order to satisfy the SAFETY comment of an unsafe block. In
| practice, in safe Rust, this knowledge shouldn't really change
| how you write your code.
| Animats wrote:
| Rust destructors are interesting.
|
| - You can't export a reference to the thing you are dropping.
| You can do that in C++. This prevents "re-animation", where
| something destroyed comes back to life or is accessed beyond
| death. Microsoft Managed C++ (early 2000s), supported re-
| animation and gave it workable semantics. Bad idea, now dead.
|
| - This is part of why Rust destructors cannot run more than
| once. Less than once is possible, as mentioned above.
|
| - There's an obscure situation with Arc and destructors. When
| an Arc counts down to 0, the destructor is run. Exactly once.
| However, Arc countdown and destructor running are not an atomic
| operation. It is possible for two threads to see an Arc in a
| strong_count == 1 state just before the Arc counts down. Never
| check strong_count to see if you are "the last owner". That
| creates a race condition.[1] I've seen that twice now. I found
| race conditions that took a day of running to hit. Use
| strong_count only for debug print.
|
| - A pattern that comes up in GUI libraries and game programming
| involves objects that are both in some kind of index and owned
| by Arcs. On drop, the object should be removed from the index.
| This is a touchy operation. The index should use weak refs, and
| you have to be prepared to get an un-upgradable Weak from the
| index.
|
| - Even worse is the case where dropping an object starts a
| deletion of something else. If the second deletion can't be
| completed from within the destructor, perhaps because it
| requires a network transaction, it's very easy to introduce
| race conditions.
|
| [1] https://github.com/rust-lang/rust/issues/117485
| Rusky wrote:
| > - You can't export a reference to the thing you are
| dropping. You can do that in C++. This prevents "re-
| animation", where something destroyed comes back to life or
| is accessed beyond death. Microsoft Managed C++ (early
| 2000s), supported re-animation and gave it workable
| semantics. Bad idea, now dead.
|
| >
|
| > - This is part of why Rust destructors cannot run more than
| once. ...
|
| This is a very backwards way to describe this, I think.
| Managed C++ only supported re-animation for garbage collected
| objects, where it is still today a fairly normal thing for a
| language to support. This is why these "destructors"
| typically go by a different name, "finalizers." Some
| languages allow finalizers to run more than once, even
| concurrently, but this is again due to their GC design and
| not a natural thing to expect of a "destructor."
|
| The design of Drop and unmanaged C++ destructors is that they
| are (by default) deterministically executed before the object
| is deallocated. Often this deallocation is not by `delete` or
| `free`, which could perhaps in principle be cancelled, but by
| a function return popping a stack frame, or some larger
| object being freed, which it simply does not make sense to
| cancel.
| hamandcheese wrote:
| > Never check strong_count to see if you are "the last
| owner".
|
| This made me think of the `im` library[0] which provides some
| immutable/copy on write collections. The docs make it seem
| like they do some optimizations when they determine there is
| only one owner:
|
| > Most crucially, if you never clone the data structure, the
| data inside it is also never cloned, and in this case it acts
| just like a mutable data structure, with minimal performance
| differences (but still non-zero, as we still have to check
| for shared nodes).
|
| I hope this isn't prone to a similar race condition!
|
| [0] https://docs.rs/im/15.1.0/im/index.html
| sestep wrote:
| The way to do this while avoiding race conditions seems to
| be `Arc::into_inner` or `Arc::get_mut`; for instance, the
| docs for `Arc::try_unwrap` mention a possible race
| condition, and recommend using `Arc::into_inner` to avoid
| it: https://doc.rust-
| lang.org/std/sync/struct.Arc.html#method.tr...
| dang wrote:
| Related. Others?
|
| _Effective Rust_ - https://news.ycombinator.com/item?id=38241974
| - Nov 2023 (10 comments)
|
| _Effective Rust (2021)_ -
| https://news.ycombinator.com/item?id=36338529 - June 2023 (204
| comments)
|
| Edit: I've put 2024 in the title above because that's what the
| page currently says. But what's the most accurate year for this
| material?
___________________________________________________________________
(page generated 2025-03-02 23:00 UTC)