@ebel i've been making my functions accept "impl AsRef<str>" which means any type that has an ".as_ref::<str>()" can be passed in directly - you just have to call .as_ref() in the function body to get at the &str.
@lifning yeah I know about that technic and have used it. Maybe I'm doing something complicated which is _too_ generic 🤔. I don't want to limit my code to Strings, but generic types. So I need to wrap my head around Borrow, like HashMap
@ebel I've been thinking of &str as like a slice ref for characters, while &String is like a &Vec of same.
I kinda wish it'd been called &[char] instead of &str... (but that would probably be wrong in some detail, like it's not indexable so can't be a slice? ugh!)
@brion oh wow `&[char]` I didn't think of that. That's another thing that's like a &str.
I presume (hope?) there's some good reason that's clear when you know enough rust.
@ebel my sense of it is that it's most flexible to take a &str when you're borrowing input, and a String when you're taking ownership.
You can always make a &str from a String at no runtime cost, but not the other way.
A big advantage of &str, like slices, is that they can be a substring of a larger string in memory. So for instance a text-file parser might be able to pass around substrings from a source buffer "for free" without copying them, and then at the point you need a copy you create a String.
@brion oh the whole "return part of a big parsed string" does sound like a great advantage.
I'm fine with the concept of slices (and slices of slices), it's just the fact that `String`/`str` are different types! 😞
@ebel @brion This post and the next one explain this nicely: https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html
A nice one on AsRef - https://www.philipdaniels.com/blog/2019/rust-api-design/
&str is not plainly indexable because it stores strings in UTF-8 encoding, so an arbitrary index may not point to the beginning of a character. You *can* slice a &str in constant time after knowing valid indices, which you get from its methods.
&[char] would be a slice of whole 32-bit characters, not as compact as UTF-8. You can index that one arbitrarily.
@ebel It's because they're two completely different types. It's like the difference between a PathBuf and a &Path, or a Vec<u8> and a &[u8].
The String is essentially a StrBuf, whereas a &str by itself is an instance of a view into a string, which may be managed by a String.
&String will contain capacity information in addition to length. &str is just a slice to a collection of bytes -- contains a pointer to the first element in the string, and the length of the string.
@mmstick what makes a &str different from a &[char] then?
@ebel Technically, a `&str` is a `&[u8]` which was validated to be UTF-8. A `&[char]` is not a valid UTF-8 representation.
@mmstick OK that makes sense I guess.
@ebel I usually opt for &str for arguments and String for return values. The borrower pattern helps make maintaining memory a bit more sane.
@jalcine Someone on the thread recommended shared these posts, and they're quite interesting, have you seen them?
The social network of the future: No ads, no corporate surveillance, ethical design, and decentralization! Own your data with Mastodon!