Por que a Vec não implementa a característica Iterator?

8

Qual é a razão do design para Vec não implementar a Iteratorcaracterística? Ter que sempre chamar iter()todos os vetores e fatias cria linhas de código mais longas.

Exemplo:

let rx = xs.iter().zip(ys.iter());

em comparação com Scala:

val rx = xs.zip(ys)
sge
fonte
Veja também Em Rust, um vetor é um Iterador?
Shepmaster # 6/19

Respostas:

14

Um iterador possui um estado de iteração. Ele deve saber qual será o próximo elemento a fornecer.

Portanto, um vetor por si só não é um iterador, e a distinção é importante. Você pode ter dois iteradores sobre o mesmo vetor, por exemplo, cada um com seu estado de iteração específico.

Mas um vetor pode fornecer um iterador, é por isso que ele implementa IntoIterator, o que permite escrever isso:

let v = vec![1, 4];
for a in v {
    dbg!(a);
}

Muitas funções ocorrem IntoIteratorquando um iterador é necessário, e é o caso disso zip, e é por isso que

let rx = xs.iter().zip(ys.iter());

pode ser substituído por

let rx = xs.iter().zip(ys);
Denys Séguret
fonte
Ótima resposta! A única coisa que me pergunto agora: por que xs.zip(ys)funciona em Scala então? Um iterador (estado) é criado automaticamente no Scala? Ou seu "tipo de lista" sempre contém um estado de iterador? Qualquer que seja a solução que a Scala use: por que a Rust não a usa?
Lukas Kalbertodt 6/11/19
5
@ DenysSéguret Porque em Rust, a distinção entre iter(), into_iter()e iter_mut()é importante.
Sebastian Redl
2
@ DenysSéguret você está certo. Eu diria para habilitá-lo apenas para iteração imutável (usando iter) e exigir uma chamada explícita iter_mutpara iteração mutável.
Jmb
2
Observe que o mesmo argumento pode ser feito ysem xs.iter().zip (ys): como você escolhe usar ys.iter()ou ys.iter_mut()?
Jmb
2
Para ys, nós usamos into_iter. O motivo é simples: ysé consumido; portanto, outros tipos de iteradores não fazem sentido.
Cerberus
4

Qual é o motivo do design para Vecnão implementar a Iteratorcaracterística?

Qual dos três iteradores ele deve implementar? Existem três tipos diferentes de iteradores que você pode obter em Vec:

  1. vec.iter()Iterator<Item = &T>,
  2. vec.iter_mut()Iterator<Item = &mut T>e modifica o vetor e
  3. vec.into_iter()fornece Iterator<Item = T>e consome o vetor no processo.

em comparação com Scala:

No Scala, ele também não é implementado Iteratordiretamente, porque Iteratorprecisa do ponteiro do próximo item que o próprio vetor não possui. No entanto, como o Scala não possui semântica de movimentação, ele só tem uma maneira de criar um iterador a partir de um vetor, para que ele possa fazer a conversão implicitamente. O Rust possui três métodos, portanto, ele deve perguntar qual você deseja.

Jan Hudec
fonte
4
into_iter()é o que consome o vetor; drainé diferente, pois apenas esvazia o vetor.
trentcl