how would you write a substring substitution with multiple chains?
I would do it the same way I asked:
fn main() { let a = "hello"; let b = a.replace("e", "a").replace("ll", "r").replace("o", "d"); println!("{}", b); }
It is you asking how to do multiple simultaneous replacements, going through a line only once, then it really becomes much more complicated.
This requires allocating new memory for each replace call, even if replacement is not required. An alternative implementation of replace can return a Cow<str> , which only includes the owned option when the replacement occurs. A hacker implementation of this might look like this:
use std::borrow::Cow; trait MaybeReplaceExt<'a> { fn maybe_replace(self, needle: &str, replacement: &str) -> Cow<'a, str>; } impl<'a> MaybeReplaceExt<'a> for &'a str { fn maybe_replace(self, needle: &str, replacement: &str) -> Cow<'a, str> { // Assumes that searching twice is better than unconditionally allocating if self.contains(needle) { self.replace(needle, replacement).into() } else { self.into() } } } impl<'a> MaybeReplaceExt<'a> for Cow<'a, str> { fn maybe_replace(self, needle: &str, replacement: &str) -> Cow<'a, str> { // Assumes that searching twice is better than unconditionally allocating if self.contains(needle) { self.replace(needle, replacement).into() } else { self } } } fn main() { let a = "hello"; let b = a.maybe_replace("e", "a") .maybe_replace("ll", "r") .maybe_replace("o", "d"); println!("{}", b); let a = "hello"; let b = a.maybe_replace("nope", "not here") .maybe_replace("still no", "i swear") .maybe_replace("but no", "allocation"); println!("{}", b); assert_eq!(b.as_ptr(), a.as_ptr()); }