Hi everybody,
I read very interesting article about AsRef<str> and Into<String> and I started using AsRef<str>
in my functions.
I quickly realized that are several problems with using self
:
trait MyTrait1 {
fn a(self) -> bool;
fn b(&self) -> bool;
}
impl<T> MyTrait1 for T
where
T: AsRef<str>,
{
fn a(self) -> bool {
self.as_ref() == " "
}
fn b(&self) -> bool {
self.as_ref() == " "
}
}
trait MyTrait2 {
// fn c(self) -> &str; // missing lifetime
fn d(&self) -> &str;
}
impl<T> MyTrait2 for T
where
T: AsRef<str>,
{
// fn c(self) -> &str {
// self.as_ref().strip_prefix(".").unwrap_or_default() // missing lifetime
// }
fn d(&self) -> &str {
self.as_ref().strip_prefix(".").unwrap_or_default()
}
}
fn main() {
let x = " ";
let y1 = x.a();
let y2 = x.a();
let x = " ";
let z1 = x.b();
let z2 = x.b();
let x = String::from(" ");
let y1 = x.a();
// let y2 = x.a(); // use of moved
let x = String::from(" ");
let z1 = x.b();
let z2 = x.b();
}
I wonder is there is a best practice of always using &self
instead of self
when self
is AsRef<str>
?
The reason I'm asking is that, strangely, the author didn't mention that in such good article.
struct Person {
name: String,
}
impl Person {
pub fn new<N>(name: N) -> Person
where
N: AsRef<str>,
{
Person {
name: name.as_ref().to_owned(),
}
}
}
fn main() {
let x = "john";
let y1 = Person::new(x);
let y2 = Person::new(x);
let x = String::from("john");
let y1 = Person::new(x);
// let y2 = Person::new(x); // use of moved
}
- fixed version:
struct Person {
name: String,
}
impl Person {
pub fn new<N>(name: &N) -> Person
where
N: ?Sized + AsRef<str>,
{
Person {
name: name.as_ref().to_owned(),
}
}
}
fn main() {
let x = "john";
let y1 = Person::new(x);
let y2 = Person::new(x);
let x = String::from("john");
let y1 = Person::new(&x);
let y2 = Person::new(&x);
}