Live data from Hacker News

Common Rust Lifetime Misconceptions (2020)

github.com

11–20 of 89 posts

Re: Common Rust Lifetime Misconceptions (2020)

#12
post #4

This is very helpful. But I find it cumbersome to mix "misconceptions" with "clarifications". To elaborate, stating "Foo is bar" as a misconception to be clarified, and then following it up with "Baz is quux", makes it very hard to follow and clearly identify what bits of information should be ingrained. In my opinion, information should only be conveyed "in the affirmative". For example, don't write "Foo is bar is n…

I wholeheartedly agree and also extend this to software I write. I try very hard to have booleans never be called e.g. disableFoo. It isn't always easy, but you glue enough logic together and then try to say it becomes very difficult. This becomes even more true when you have a language that has unset or null type values and then configurations for those settings where the logic gets even nastier because usually you want unset to be false. If you have a negatively declared variable in this case, you have to check if it is true OR it is unset, whereas if it is a positively named thing, simply checking for a truthy value is adequate, more concise, and less error prone.

Re: Common Rust Lifetime Misconceptions (2020)

#14
post #4

This is very helpful. But I find it cumbersome to mix "misconceptions" with "clarifications". To elaborate, stating "Foo is bar" as a misconception to be clarified, and then following it up with "Baz is quux", makes it very hard to follow and clearly identify what bits of information should be ingrained. In my opinion, information should only be conveyed "in the affirmative". For example, don't write "Foo is bar is n…

[deleted]

Re: Common Rust Lifetime Misconceptions (2020)

#16

How I bail myself out of Rust lifetime problems as somebody who probably learned Rust the wrong way (by just trying to build stuff as if it were C/node.js and run into problems instead of slowing down + reading): 1. .clone() / .to_owned() 1. String -> vs &String/&str with & borrow 1. lazy_static / OnceCell + Lazy / OnceLock 1. Arc > with lots of .lock(). What would start off as like NULL in Java/C is Arc >> and you h…

Good advice, though I'd recommend Rc > instead of Arc > if you're not sharing the data between threads, to avoid synchronization overhead. I use Arc pretty rarely.

tokio is so wide spread now such that Arc> is coincidentally the right choice.

I'm not saying that's a good thing.

Re: Common Rust Lifetime Misconceptions (2020)

#17

I just clone everywhere and write Rust like a high level language. Then, once I need to optimize more, if I ever do (as Rust is many times faster than other languages even with liberal cloning), then I simply go through and remove the clone where needed.

Another technique for dodging [manual] lifetimes is not store references in struct fields etc.

Re: Common Rust Lifetime Misconceptions (2020)

#18

How I bail myself out of Rust lifetime problems as somebody who probably learned Rust the wrong way (by just trying to build stuff as if it were C/node.js and run into problems instead of slowing down + reading): 1. .clone() / .to_owned() 1. String -> vs &String/&str with & borrow 1. lazy_static / OnceCell + Lazy / OnceLock 1. Arc > with lots of .lock(). What would start off as like NULL in Java/C is Arc >> and you h…

I think there's a lot to be gained by not writing Rust like C, to the extent that it might be worth taking some time to pick up another language (maybe a lisp variant?) first.

2.) Be careful because &String is not &str, although in many cases you can pretend thanks to magic of AsRef/AsDeref.

4.) If you find yourself calling is_none, rethink things a bit. Pattern matching and the various destructuring (e.g. if let) features are some of the most powerful tools at your disposal with Rust. This is where experience with something else first (e.g. Elixir) can be helpful.

  I rarely introduce a lifetime to a struct/impl.
IMO the big use case here is &str.

  Arc kind of bails you out of a lot
While that's totally reasonable it's good to remember that you're essentially trading compile time guarantees for runtime ones. If you can figure out how to beat the borrow checker into submission that's one less thing to debug at runtime.

  primitive like u32 and it's borrowed and you had to dereference it or clone it.
The primitive types should all implement Copy which means you should (almost?) never have to explicitly clone them. Dereferencing is another story tho.

Re: Common Rust Lifetime Misconceptions (2020)

#19

How I bail myself out of Rust lifetime problems as somebody who probably learned Rust the wrong way (by just trying to build stuff as if it were C/node.js and run into problems instead of slowing down + reading): 1. .clone() / .to_owned() 1. String -> vs &String/&str with & borrow 1. lazy_static / OnceCell + Lazy / OnceLock 1. Arc > with lots of .lock(). What would start off as like NULL in Java/C is Arc >> and you h…

Good advice, though I'd recommend Rc > instead of Arc > if you're not sharing the data between threads, to avoid synchronization overhead. I use Arc pretty rarely.

Eh, I don't think the overhead of an uncontested lock acquire is all that much.

Re: Common Rust Lifetime Misconceptions (2020)

#20

How I bail myself out of Rust lifetime problems as somebody who probably learned Rust the wrong way (by just trying to build stuff as if it were C/node.js and run into problems instead of slowing down + reading): 1. .clone() / .to_owned() 1. String -> vs &String/&str with & borrow 1. lazy_static / OnceCell + Lazy / OnceLock 1. Arc > with lots of .lock(). What would start off as like NULL in Java/C is Arc >> and you h…

Using `clone` etc when it's easier is actually common advice, it's perfectly OK to not have borrowing everywhere if you don't need it. My usual starting point / default / rule of thumb is to take references as parameters and return owned values (for example, take `&str` as an argument, return an owned `String`).

IMO stringy data is a good example of where you should think about what you're returning in part because common APIs (e.g. regex) will take a more nuanced approach.

If you're creating a new string, then sure return String. But if you have a path where you could just return the original input, consider returning a Cow.

Post reply on HN