나중에 map, flatmap 등과 같은 기능을 적용 할 때 필터 대신 withFilter를 사용하는 것이 항상 더 성능이 좋습니까?
map, flatmap 및 foreach 만 지원되는 이유는 무엇입니까? (forall / exists와 같은 예상 기능)
답변:
에서 스칼라 문서 :
참고 사이의 차이
c filter p
와c withFilter p
후자는 단지 다음의 영역으로 제한하는 반면, 전자는, 새로운 집합을 생성하는이고map
,flatMap
,foreach
, 및withFilter
작업.
따라서 filter
원래 컬렉션을 가져와 새 컬렉션을 생성하지만 withFilter
필터링되지 않은 값을 나중에 map
/ flatMap
/ withFilter
호출에 엄격하게 (즉, 느리게) 전달 하여 (필터링 된) 컬렉션을 통한 두 번째 패스를 절약합니다. 따라서 이러한 후속 메서드 호출을 전달할 때 더 효율적입니다.
실제로, withFilter
는 이러한 방법의 체인으로 작업하도록 특별히 설계되었으며, 이는 이해를위한 것입니다. 이를 위해 다른 메서드 (예 : forall
/ exists
)가 필요하지 않으므로 FilterMonadic
반환 유형에 추가되지 않았습니다 withFilter
.
view
지도 / 필터가 게 으르도록 하려면 사용 합니다.
view
과 의 정확한 차이점은 withFilter
무엇입니까? 보기가 사용되지 않는 이유는 무엇 for-loops
입니까?
Don’t create temporary collections
링크 된 섹션에서 검색 할 수 있습니다 .
withFilter
Martin Odersky는 Coursera의 Scala 과정에서 명시 적으로 사용합니다. 그가 그렇게한다는 점을 감안할 때, 그 차이는 일반적으로 한 캐릭터에 불과하지만 다른 사람들도 그렇게하는 것에 대해 위로를 줄 수 있습니다. 예를 들어 seq.view filter p
대 seq withFilter p
.
의 또한 어둠의 땅의 우수한 대답 , 나는 사이의 차이의 직관적 인 예를 가지고 싶습니다 filter
와 withFilter
.
다음 코드를 살펴 보겠습니다.
val list = List(1, 2, 3)
var go = true
val result = for(i <- list; if(go)) yield {
go = false
i
}
대부분의 사람들 result
은 List(1)
. 이것은 Scala 2.8 이후의 경우입니다.
val result = list withFilter {
case i => go
} map {
case i => {
go = false
i
}
}
보시다시피 번역은 조건을 withFilter
. 이전 Scala 2.8, for-comprehension은 다음과 같이 번역되었습니다.
val r2 = list filter {
case i => go
} map {
case i => {
go = false
i
}
}
을 사용 filter
하면의 값 result
이 상당히 다릅니다 List(1, 2, 3)
.. 우리가 go
플래그 false
를 만들고 있다는 사실 은 필터가 이미 완료 되었기 때문에 필터에 영향을 미치지 않습니다. 다시 말하지만 Scala 2.8에서이 문제는 withFilter
. 경우 withFilter
사용되며, 상태는 소자가 내부에 액세스 할 때마다 평가 map
방법.
참조 :-p.120, Scala in action (Scala 2.10 포함), Manning Publications, Milanjan Raychaudhuri- 이해를위한 번역에 대한 Odersky의 생각
forall / exist가 구현되지 않은 주된 이유 는 사용 사례가 다음과 같기 때문 입니다.
forall / exist 를 구현하려면 게으름을 잃어 버리고 모든 요소를 얻어야합니다.
예를 들면 다음과 같습니다.
import scala.collection.AbstractIterator
class RandomIntIterator extends AbstractIterator[Int] {
val rand = new java.util.Random
def next: Int = rand.nextInt()
def hasNext: Boolean = true
}
//rand_integers is an infinite random integers iterator
val rand_integers = new RandomIntIterator
val rand_naturals =
rand_integers.withFilter(_ > 0)
val rand_even_naturals =
rand_naturals.withFilter(_ % 2 == 0)
println(rand_even_naturals.map(identity).take(10).toList)
//calling a second time we get
//another ten-tuple of random even naturals
println(rand_even_naturals.map(identity).take(10).toList)
참고 ten_rand_even_naturals는 여전히 반복자입니다. toList 를 호출 할 때만 난수가 생성되고 체인으로 필터링됩니다.
참고 지도 (신원) 에 해당 매핑 (I => I) 및 원래 형으로 withFilter 오브젝트 다시 전환하기 위해 여기에 (예를 들어 수집 스트림, 반복자)를 사용
수익을 위해 사용하는 것은 다음과 같은 해결 방법이 될 수 있습니다.
for {
e <- col;
if e isNotEmpty
} yield e.get(0)