Ответ 1
Для конкретной проблемы вам не нужна специализация:
struct State {
string: String,
}
impl State {
fn string<F>(mut self, mut f: F) -> Self
where F: Thing
{
self.string = f.thing(self.string);
self
}
}
trait Thing {
fn thing(&mut self, s: String) -> String;
}
impl Thing for String {
fn thing(&mut self, _s: String) -> String {
self.clone()
}
}
impl<F> Thing for F
where F: FnMut(String) -> String
{
fn thing(&mut self, s: String) -> String {
(self)(s)
}
}
fn main() {
let state = State { string: String::from("foo") };
assert_eq!(state.string, "foo");
let state = state.string(|old| old + "bar");
assert_eq!(state.string, "foobar");
let state = state.string(String::from("baz"));
assert_eq!(state.string, "baz");
}
Вы можете либо потребовать FnOnce
, либо реализовать признак для &str
. Прямо сейчас выделение String
не используется, что приводит к небольшой неэффективности.
Затем вы могли бы реализовать признак несколько раз для интересных типов:
struct State {
string: String,
vec: Vec<u8>,
}
impl State {
fn string<F>(mut self, mut f: F) -> Self
where F: Thing<String>
{
self.string = f.thing(self.string);
self
}
fn vec<F>(mut self, mut f: F) -> Self
where F: Thing<Vec<u8>>
{
self.vec = f.thing(self.vec);
self
}
}
trait Thing<T> {
fn thing(&mut self, s: T) -> T;
}
impl Thing<String> for String {
fn thing(&mut self, _s: String) -> String {
self.clone()
}
}
impl<F> Thing<String> for F
where F: FnMut(String) -> String
{
fn thing(&mut self, s: String) -> String {
(self)(s)
}
}
impl Thing<Vec<u8>> for Vec<u8> {
fn thing(&mut self, _s: Vec<u8>) -> Vec<u8> {
self.clone()
}
}
impl<F> Thing<Vec<u8>> for F
where F: FnMut(Vec<u8>) -> Vec<u8>
{
fn thing(&mut self, s: Vec<u8>) -> Vec<u8> {
(self)(s)
}
}
fn main() {
let state = State { string: String::from("foo"), vec: vec![1] };
assert_eq!(state.string, "foo");
let state = state.string(|old| old + "bar");
assert_eq!(state.string, "foobar");
let state = state.string(String::from("baz"));
assert_eq!(state.string, "baz");
assert_eq!(state.vec, [1]);
let state = state.vec(|mut old: Vec<u8>| {
old.push(2);
old
});
assert_eq!(state.vec, [1, 2]);
let state = state.vec(vec![3]);
assert_eq!(state.vec, [3]);
}
Я считаю, что повторение может выполняться макросом:
macro_rules! thing {
($t: ty) => {
impl Thing<$t> for $t {
default fn thing(&mut self, _val: $t) -> $t {
self.clone()
}
}
impl<F> Thing<$t> for F
where F: FnMut($t) -> $t
{
fn thing(&mut self, val: $t) -> $t {
(self)(val)
}
}
}
}
thing!(String);
thing!(Vec<u8>);