Hey folks, I have such a python function:
def foo(url, prefix="http://google.com/?s="):
if not url.startswith('http'):
url = prefix + url
print(url)
and I want to translate this function in Rust,this is what I have done:
fn foo(url:&str){
let mut prefix="http://google.com/?s=";
if !url.starts_with("http") {
let mut prefix_url = prefix.clone();
let url = prefix_url.push_str(url);
}
println!("{:?}",url);
}
But my Rust function could not produce the expected result, it seems it is a feature of String
.
How could I get the correct result ?
The push_str()
mutates the string, it doesn't create a new copy with the url
appended. That means the push_str()
doesn't return anything useful, kinda like how some_list.append()
doesn't return anything (well... technically it returns None
). The Rust equivalent of this is the empty tuple, ()
.
In the let url = ...
line you aren't actually updating the url
parameter. Instead you're creating a new variable (which just happens to be called url
) which is only valid for the lifetime of the if
block. It's to do with how scopes work, you may want to google "shadowing".
That means when you do let url = prefix_url.push_str(url);
your new url
variable contains ()
. Then when you leave the if
block and do println!("{:?}", url)
you're printing the original url
parameter.
Here's a playground snippet which annotates what's happening. And this is probably more what you were meaning to do.
1 Like
A solution that avoids unnecessary heap activity, possibly there are better solutions:
use std::borrow::Cow;
fn foo(url: &str) {
let mut url: Cow<str> = url.into();
if !url.starts_with("http") {
url = ["http://google.com/?s=", &url].concat().into();
}
println!("{}", url);
}
2 Likes
it makes sense, your explaination is super clear
wow, it works. I check the api document and example about Cow
, it says:
The type Cow is a smart pointer providing clone-on-write functionality: it can enclose and provide immutable access to borrowed data, and clone the data lazily when mutation or ownership is required.
But I still think it is not easy understand this feature
1 Like