惯用语附加操作

时间:2016-12-18 20:07:34

标签: rust idiomatic

我正在编写一个函数,将内容从一个Vec传输到另一个。

我设法写了两个不同版本的相同代码。一个更干净,但可能更慢。

版本1:

fn move_values<T>(buffer: &mut Vec<T>, recipient: &mut Vec<T>) {
    loop {
        let value = buffer.pop();
        if value.is_none() {
            return;
        }
        recipient.push(value.unwrap());
    }
}

第2版:

fn move_values<T>(buffer: &mut Vec<T>, recipient: &mut Vec<T>) {
    for value in buffer.iter() {
        recipient.push(value.clone());
    }

    buffer.clear();
}

我最初的直觉是版本1更快,因为它只需要一次通过缓冲区;而版本2更“生锈”,因为它涉及迭代集合而不是使用loop

一般来说,哪一种更惯用或“更好的做法”?

注意,我知道append,我正在尝试用手进行教育。

1 个答案:

答案 0 :(得分:3)

都不是。有一个内置的操作,Vec::append

  

将其他元素移动到Self,将其他元素留空。

fn move_values<T>(buffer: &mut Vec<T>, recipient: &mut Vec<T>) {
    recipient.append(buffer);
}

你的两个函数都没有编译:

fn move_values_1<T>(buffer: &mut Vec<T>, recipient: &mut Vec<T>) {
    loop {
        let value = buffer.pop();
        if value.is_none() {
            return;
        }
        recipient.push_front(card.unwrap());
    }
}
error[E0425]: unresolved name `card`
 --> src/main.rs:7:30
  |
7 |         recipient.push_front(card.unwrap());
  |                              ^^^^ unresolved name
fn move_values_2<T>(buffer: &mut Vec<T>, recipient: &mut Vec<T>) {
    for value in buffer.iter() {
        recipient.push_front(value.clone());
    }

    buffer.clear();
}
error: no method named `push_front` found for type `&mut std::vec::Vec<T>` in the current scope
 --> src/main.rs:7:19
  |
7 |         recipient.push_front(card.unwrap());
  |                   ^^^^^^^^^^
  

如果我自己实施

嗯,这是为你实施的原因,但是确定......让我们深入了解。

通过模式匹配检查是否通常可以避免is_someis_none。例如:

fn move_values_1<T>(buffer: &mut Vec<T>, recipient: &mut Vec<T>) {
    while let Some(v) = buffer.pop() {
        recipient.push(v);
    }
}

当然,这会以反向顺序移动所有内容,因为推送和弹出到Vec都会发生在最后。

调用clone并不能达到你想要的效果,除非你的特质界限表明T实现了Clone。否则,您只是克隆引用本身。

如果从一个集合中排除值并将它们插入另一个集合中,则可以避免克隆的需要:

for value in buffer.drain(..) {
    recipient.push(value);
}

但是for循环是愚蠢的,只使用迭代器的extend集合:

recipient.extend(buffer.drain(..));

仍然使用内置的append方法在同一类型的集合之间进行传输时,因为它可能针对精确的数据布局进行了优化,并且可能是专门的对于某些类型的数据。