7 ms·
I have the same problem with strings as well. I think I understand the difference between String and &str but I wish it’d automatically convert String into &str
by http-teapot 6y ago
I have the same problem with strings as well. I think I understand the difference between String and &str but I wish it’d automatically convert String into &str when a function expects it.
Example: `std::env::var(“SOME_PARAM”).unwrap_or_else(|_| “localhost”.to_string())`
It just seems odd to me, something tells me there is a better way to do this but I couldn’t find it.
- woodruffw 6y ago> I have the same problem with strings as well. I think I understand the difference between String and &str but I wish it’d automatically convert String into &str when a function expects it. Yep! My understanding is that `AsRef<str>` is the right way to do this automatic conversion but I learned that by reading library code, not from the standard documentation. It'd be awfully nice if the compiler could do those sorts of conversions automatically; injecting `AsRef` everywhere adds a lot of visual clutter.
- Ciantic 6y ago> injecting `AsRef` everywhere adds a lot of visual clutter I agree! `fn foo<T: AsRef<str>>(s: T)` This is so difficult to read, one has to jump back and forth with eyes to make any sense of these. Why couldn't there be easier syntax for "AsReffing"? E.g. `fn foo(s: @str)` I invented @-sign there.
- stuhood 6y agoCan use `impl Trait` I think? ``` fn foo(s: impl AsRef<str>) ```
- steveklabnik 6y agoSyntax like @T was actually a type in ancient Rust. People really, really hated having even more sigils in the language, so we ended up removing them. There was also ~T.
- jcranmer 6y agoIIRC, one of the sigils was for reference counting, and there was to be another one for garbage-collected types? (I'm recalling the lunch conversations from when I sat in the room with all the Rust interns).
- steveklabnik 6y ago@T was supposed to be a GC'd type, but ended up being a refcounted type. It was removed before it actually turned into a GC'd type. ~T was Box<T>. However, one issue here was that they didn't compose in the same way as types today; ~str existed, for example, but was not the exact same as String in terms of memory layout. Conceptually they're the same thing though.
- mrlonglong 6y agoMassive turbofish! :-D
- twic 6y agoThere, you're converting a &str into a String, not String into &str. That involves allocation, so i think it's quite right that it's explicit.
- http-teapot 6y agoSince "localhost" isn't assigned to a variable, couldn't it be a safe implicit conversion?
- PudgePacket 6y agoIt's not really important whether it's assigned to a variable or not. It's important that "potentially expensive" operations like memory allocation are obvious. So you either need to call to_string, or call String::new("localhost").
- twic 6y agoThe thing is, "localhost" ends up being some characters [1] in the read-only section of the binary. You can safely read that, but you can't modify it or delete it (that won't work, and if it did work, it would make a hell of a mess!). So this is fine: let host: &str = "localhost"; Because a &str is just a read-only pointer to some characters [1], and you're just setting host to be a pointer to those characters in the read-only section. But this is not: let host: String = "localhost"; Because a String is not just a pointer, it's a pointer which implies ownership of an allocation on the heap [1]. That means you can modify the contents of a String, and when the String is dropped, that allocation will be freed. You can't just set up a String using a pointer into the read-only section. You need to make an allocation, copy the characters into it, and use that. Which is what str::to_string() does. [1] And a length, but we can ignore that for now.