Сжатие векторов одного типа приводит к закрытию карты разных типов

Aug 16 2020

Задний план

Учитывая тип варианта перечисления (не копируемый):

enum AstNode {
  Op(Func, Box<AstNode>, Box<AstNode>),
  Val(f64),
  // others...
}

Попытка запустить операцию над двумя такими векторами:

fn apply_func_iterative(func: Func, lhs: Vec<AstNode>, rhs: Vec<AstNode>) -> Vec<AstNode> {
    lhs.iter().zip(rhs).map(|(&l,r)| apply_func(func,l,r)).collect()  // l and r are declared differently!
}

fn apply_func(func: Func, lhs: AstNode, rhs: AstNode) -> AstNode {
    // magic happens here!
}

Внутри замыкания lhsэлементы принимают тип, l: &AstNodeтогда как заархивированные rhsэлементы принимают тип l: AstNode. (Обратите внимание на различные объявления в закрывающем кортеже).

Вопросов

Почему это так?

Есть ли способ перебирать элементы вектора по значению, а не по ссылке? Казалось бы, это возможно из наблюдаемого поведения заархивированных элементов.

(В этом примере это различие приводит к небольшой странности в объявлении синтаксиса, но на практике я столкнулся с программой проверки заимствований при передаче ссылочной переменной в функцию)

Отказ от ответственности: я новичок в Rust

Ответы

6 kmdreko Aug 16 2020 at 04:55

Этот Iterator::zipметод не делает ничего особенного, он просто объединяет оба итератора. Вы обнаружите, что это lhs.iter()дает, Iterator<&AstNode>а время rhsдает Iterator<AstNode>( &против не- &).

Есть ли способ перебирать элементы вектора по значению, а не по ссылке? Казалось бы, это возможно из наблюдаемого поведения заархивированных элементов.

Да, есть способ контролировать это поведение. Главное - заметить, что zip()аргумент rhsдолжен реализовывать эту IntoIteratorчерту. По сути, zip()вызовет rhs.into_iter()получение от него итератора. Обычное поведение состоит в том, что заимствует.iter() только источник и поэтому может предоставлять только ссылки на его значения. В то время как потребляет или «становится владельцем» источника и может давать собственные ценности..into_iter()

Комбинируя их, вы можете lhs.into_iter().zip(rhs)получить итератор по значениям (AstNode, AstNode)или использовать lhs.iter().zip(rhs.iter())для получения итератора по ссылкам (&AstNode, &AstNode).