Scala : Scala 컬렉션에서 Traversable 특성과 Iterable 특성의 차이점은 무엇입니까?


98

나는 살펴 보았다 이 질문에 여전히의 Iterable과에 이동 특성의 차이를 이해하지 않습니다. 누군가 설명 할 수 있습니까?


2
더 이상 없습니다 Traversable에서 스칼라 2.13 (여전히를 위해 사용되지 않는 별칭으로 유지 Iterable2.14까지)
자비에 Guihot

답변:


121

간단히 말해서, 반복자는 상태를 유지하고 트래버 서블은 유지하지 않습니다.

A Traversable에는 foreach. 당신이 호출 할 때 foreach, 컬렉션은 전달 기능을 그것을 유지하는 모든 요소를 하나씩 공급됩니다.

반면 에는를 반환하는 Iterable추상 메서드 iterator가 있습니다 Iterator. 당신이 호출 할 수 nextIterator당신의 선택의 시점에서 다음의 요소를 얻을 수 있습니다. 그렇게 할 때까지 컬렉션의 위치와 다음 작업을 추적해야합니다.


4
그러나 Iterableextends Traversable, 그래서 나는 당신이 Traversables가 아닌 Iterables 를 의미한다고 생각합니다 .
Robin Green

4
@RobinGreen 나는 Traversable인터페이스를 준수하는 것은 상태를 유지할 필요가 없지만 인터페이스를 준수한다는 것을 의미 Iterator합니다.
Daniel C. Sobral 2013

10
Traversable이다들 Iterable어떤 반복 상태를 유지하지 않습니다. 그것은 것 Iterator생성에 의해 반환 된 Iterable상태를 그대로 유지합니다.
Graham Lea

1
2.13부터 Traversable 특성은 더 이상 사용되지 않습니다. Stefan Zeiger의 말을 인용하자면, "Traversable 추상화는 현재 라이브러리에서 그 비중을 차지하지 않았으며 새로운 디자인에서 다시 드러나지 않을 것입니다. 우리가 원하는 모든 것을 Iterable로 표현할 수 있습니다."
Igor Urisman

226

불고 빨기의 차이로 생각하십시오.

Traversables foreach또는 파생 메서드를 호출하면 한 번에 하나씩 해당 값을 함수에 불어 넣어 반복을 제어 할 수 있습니다.

으로 Iterator에 의해 반환 Iterable하지만, 당신은 다음 중 하나 자신에게 이동할 때 제어, 그것의 값을 빨아.


49
사람들이 전화를 걸 때 사용 밀어당기 대신 불고 하고 흡입 하여 열린 마음처럼,하지만.
Martijn

2
내 다음 인터뷰에서 물었을 때 이것을 잊지 마십시오
thestephenstanton

23

tl; dr IterablesTraversables상태 저장을 생성 할 수 있습니다.Iterators


우선, 그가 알 Iterable의 subtrait됩니다 Traversable.

둘째,

  • Traversableforeach다른 모든 것에서 사용되는 메서드를 구현해야합니다 .

  • Iterableiterator다른 모든 것에서 사용되는 메서드를 구현해야합니다 .

예를 들어, 상기의 구현 find을위한 Traversable용도 foreach(이해하는 비아)과는 슬로우 BreakControl충분한 요소가 발견 된 후 반복을 중지하는 예외.

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
  }
}

반대로, Iterable빼기는이 구현을 재정의하고를 호출합니다 find.이 Iterator경우 요소가 발견되면 반복이 중지됩니다.

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
  }
}

Traversable반복을 위해 예외를 던지지 않는 것이 좋지만 .NET을 사용할 때 부분적으로 반복하는 유일한 방법 foreach입니다.

하나의 관점 Iterable에서는를 foreach사용하여 쉽게 구현할 iterator수 있지만 실제로를 iterator사용하여 구현할 수 없기 때문에 더 까다 롭고 강력한 특성 foreach입니다.


요약 Iterable하면 stateful을 통해 반복을 일시 중지, 재개 또는 중지하는 방법을 제공합니다 Iterator. 을 사용하면 Traversable전부 또는 전혀 없습니다 (흐름 제어에 대한 예외는 제외).

대부분의 경우 중요하지 않으며 더 일반적인 인터페이스가 필요합니다. 그러나 반복에 대한보다 맞춤화 된 제어가 필요한 Iterator경우 Iterable.


1

Daniel의 대답은 좋은 것 같습니다. 내 말로 표현할 수 있는지 보자.

따라서 Iterable은 한 번에 하나씩 요소를 탐색하고 (next () 사용) 원하는대로 중지하고 이동할 수있는 반복자를 제공 할 수 있습니다. 이를 위해 반복자는 요소의 위치에 대한 내부 "포인터"를 유지해야합니다. 그러나 Traversable은 멈추지 않고 한 번에 모든 요소를 ​​순회하는 foreach 방법을 제공합니다.

Range (1, 10)과 같은 것은 Traversable 상태로 정수 2 개만 있으면됩니다. 그러나 Iterable로서 Range (1, 10)는 상태에 대해 3 개의 정수를 사용해야하는 반복자를 제공하며, 그중 하나는 인덱스입니다.

Traversable도 foldLeft, foldRight를 제공한다는 점을 고려하면 foreach는 알려진 고정 된 순서로 요소를 탐색해야합니다. 따라서 Traversable에 대한 반복기를 구현할 수 있습니다. 예 : def iterator = toList.iterator

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.