Eu olhei para esta questão, mas ainda não entendo a diferença entre traços Iteráveis e Traversáveis. Alguém pode explicar?
Eu olhei para esta questão, mas ainda não entendo a diferença entre traços Iteráveis e Traversáveis. Alguém pode explicar?
Respostas:
Para simplificar, os iteradores mantêm o estado, os percorríveis não.
Um Traversabletem um método abstrato: foreach. Quando você chama foreach, a coleção alimenta a função passada com todos os elementos que ela mantém, um após o outro.
Por outro lado, an Iterabletem como método abstrato iterator, que retorna um Iterator. Você pode chamar nextum Iteratorpara obter o próximo elemento na hora de sua escolha. Até que você faça isso, ele precisa manter o controle de onde estava na coleção e do que vem a seguir.
Iterableestende Traversable, então eu acho que você quer dizer Traversables que não são Iterables.
Traversableinterface não exige manutenção do estado, ao passo que o cumprimento da interface exige Iterator.
Traversables que são Iterablenão mantêm nenhum estado de iteração. É o Iteratorcriado e devolvido pelo Iterableque mantém o estado.
Pense nisso como a diferença entre soprar e sugar.
Quando você chama um Traversables foreach, ou seus métodos derivados, ele vai soprar seus valores em sua função, um de cada vez - portanto, ele tem controle sobre a iteração.
Com o Iteratorretorno de um Iterablepensamento, você suga os valores dele, controlando quando passar para o próximo.
tl; dr Iterables são Traversablesque podem produzir statefulIterators
Primeiro, saiba que Iterableé o subtítulo de Traversable.
Segundo,
Traversablerequer a implementação do foreachmétodo, que é usado por todo o resto.
Iterablerequer a implementação do iteratormétodo, que é usado por todo o resto.
Por exemplo, a implementação de findpara Traversableusa foreach(por meio de um para compreensão) e lança uma BreakControlexceção para interromper a iteração assim que um elemento satisfatório for encontrado.
trait TravserableLike {
def find(p: A => Boolean): Option[A] = {
var result: Option[A] = None
breakable {
for (x <- this)
if (p(x)) { result = Some(x); break }
}
result
}
}
Em contraste, a Iterablesubtração substitui essa implementação e chama findo Iterator, que simplesmente para de iterar assim que o elemento é encontrado:
trait Iterable {
override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
iterator.find(p)
}
trait Iterator {
def find(p: A => Boolean): Option[A] = {
var res: Option[A] = None
while (res.isEmpty && hasNext) {
val e = next()
if (p(e)) res = Some(e)
}
res
}
}
Seria bom não lançar exceções para a Traversableiteração, mas essa é a única maneira de iterar parcialmente ao usar apenas foreach.
De uma perspectiva, Iterableé o traço mais exigente / poderoso, já que você pode facilmente implementar foreachusing iterator, mas não pode realmente implementar iteratorusing foreach.
Em resumo, Iterablefornece uma maneira de pausar, retomar ou parar a iteração por meio de um stateful Iterator. Com Traversable, é tudo ou nada (sem exceções para controle de fluxo).
Na maioria das vezes, isso não importa e você desejará uma interface mais geral. Mas se você precisar de um controle mais personalizado sobre a iteração, precisará de um Iterator, que pode ser recuperado de um Iterable.
A resposta de Daniel parece boa. Deixe-me ver se consigo colocar em minhas próprias palavras.
Portanto, um Iterable pode fornecer um iterador, que permite percorrer os elementos um de cada vez (usando next ()) e parar e prosseguir quando quiser. Para fazer isso, o iterador precisa manter um "ponteiro" interno para a posição do elemento. Mas um Traversable fornece o método, foreach, para percorrer todos os elementos de uma vez sem parar.
Algo como Range (1, 10) precisa ter apenas 2 inteiros como estado de Traversable. Mas Range (1, 10) como um Iterable fornece um iterador que precisa usar 3 inteiros para o estado, um dos quais é um índice.
Considerando que Traversable também oferece foldLeft, foldRight, seu foreach precisa atravessar os elementos em uma ordem conhecida e fixa. Portanto, é possível implementar um iterador para um Traversable. Ex: def iterator = toList.iterator
Traversableno Scala 2.13 (ainda é mantido como um apelido obsoletoIterableaté 2.14)