Проведение экспериментов с новыми типами и поиск наиболее эффективного и эргономичного способа преобразования элементов в коллекциях. Для единичных значений вполне нормально работают стандартные черты преобразования типов:
pub struct Tag(String);
impl From<Tag> for String {
fn from(v: Tag) -> String {
v.0
}
}
impl From<String> for Tag {
fn from(v: String) -> Tag {
Tag(v)
}
}
impl AsRef<String> for Tag {
fn as_ref(&self) -> &String {
&self.0
}
}
impl<'a> From<&'a Tag> for String {
fn from(t: &Tag) -> String {
t.0.clone()
}
}
Но я начинаю сталкиваться с проблемами, когда хочу разобраться со списками предметов. Скажем (в целях иллюстрации) у меня есть функция, которая обрабатывает теги, и еще несколько абстрактных функций, которые занимаются записью строк в БД:
fn process_item(tags: &Vec<Tag>) {
process_array_of_strings(tags);
}
fn process_array_of_strings(strings: &Vec<String>) {
// ...
}
Это не скомпилируется, потому что Rust не может привести tags
к Vec<String>
, и мне кажется, что должен быть способ сделать это более легко, чем:
fn process_item(tags: &Vec<Tag>) {
let str_tags: Vec<String> = tags.iter().map(|t| t.into()).collect();
process_array_of_strings(&str_tags);
}
... который помимо многословности включает в себя гораздо больше промежуточной памяти, чем мне бы хотелось. Обратное преобразование также является проблемой, но предположительно будет реализовано таким же образом.
Здесь могут присутствовать некоторые дополнительные вещи, например, следует ли мне отправлять Vec
ссылок, а не значений, и действительно ли это хорошая идея для реализации преобразования типов из ссылочных типов.