2013-03-20 3 views
1

제가 설명 할 수없는 결과가 나오는 테스트가 있습니다.스칼라 컬렉션을 사용할 때 이상한 결과가 있습니다.

첫 번째 테스트는 필터 매핑 4 개 요소를 포함하는 목록을 줄이기 않습니다 동안 한번 필터링시 각 요소에 대해, 한 번 각 요소 : I 예상대로 카운터가 11 배 증가

{ 
    val counter = new AtomicInteger(0) 
    val l = List(1, 2, 3, 4) 
    val filtered = l.filter{ i => 
     counter.incrementAndGet() 
     true 
    } 
    val mapped = filtered.map{ i => 
     counter.incrementAndGet() 
     i*2 
    } 
    val reduced = mapped.reduce{ (a, b) => 
     counter.incrementAndGet() 
     a+b 
    } 
    println("counted " + counter.get + " and result is " + reduced) 
    assert(20 == reduced) 
    assert(11 == counter.get) 
} 

을 매핑 및 3 번을 추가하여 4 가지 요소를 추가합니다.

사용하여 와일드 카드 결과 변경 :

{ 
    val counter = new AtomicInteger(0) 
    val l = List(1, 2, 3, 4) 
    val filtered = l.filter{ 
     counter.incrementAndGet() 
     _ > 0 
    } 
    val mapped = filtered.map{ 
     counter.incrementAndGet() 
     _*2 
    } 
    val reduced = mapped.reduce{ (a, b) => 
     counter.incrementAndGet() 
     a+b 
    } 
    println("counted " + counter.get + " and result is " + reduced) 
    assert(20 == reduced) 
    assert(5 == counter.get) 
} 

나는 감소 (코드 나던 컴파일)에 와일드 카드를 사용하는 방법을 작동하지 않을 수 있습니다,하지만 지금은, 카운터는 5 회로 증가!

질문 1 : 와일드 카드가 카운터를 호출하는 횟수를 변경하는 이유는 무엇이며 어떻게 작동합니까?

내 두 번째 관련 질문. 뷰에 대한 나의 이해는 모나드 메서드에 전달 된 함수를 느리게 실행한다는 것이었지만 다음 코드는이를 보여주지 않습니다.

{ 
    val counter = new AtomicInteger(0) 
    val l = Seq(1, 2, 3, 4).view 
    val filtered = l.filter{ 
     counter.incrementAndGet() 
     _ > 0 
    } 
println("after filter: " + counter.get) 
    val mapped = filtered.map{ 
     counter.incrementAndGet() 
     _*2 
    } 
println("after map: " + counter.get) 
    val reduced = mapped.reduce{ (a, b) => 
     counter.incrementAndGet() 
     a+b 
    } 
println("after reduce: " + counter.get) 
    println("counted " + counter.get + " and result is " + reduced) 
    assert(20 == reduced) 
    assert(5 == counter.get) 
} 

출력은 다음과 같습니다

after filter: 1 
after map: 2 
after reduce: 5 
counted 5 and result is 20 

질문 # 2 : 어떻게 기능이 바로 실행되는 거지? 나는 당신은 아마

filter { 
    println 
    _ > 0 
} 

filter{ i => 
    println 
    i > 0 
} 

을 의미하지만 스칼라는 다른 생각을 가지고 생각하고 스칼라 2.10

+0

정말 Rex Kerr의 대답을 받아 들여야합니다 (그리고 칭찬할만한 말은 아닙니다)! –

+0

그래도 경험에 따르면 다른 답변을 기다리는 것이 좋습니다. –

답변

11

을 사용하고

. 그 이유는

{ println; _ > 0 } 

먼저 인쇄 뭔가, 다음 > 0 기능을 반환하는 문이라는 것이다. 결과적으로 당신이 상상할 수있는

println 
val temp = (i: Int) => i > 0 // Temporary name, forget we did this! 
val p = temp 
filter(p) 

에 해당하는

val p = { println; (i: Int) => i > 0 } 
filter(p) 

잘 작동을하지 않습니다 그래서 동일합니다, 당신은 기능을 지정하는 재미있는 방법으로 무슨 일을하는지 해석 당신이 원하는 방식대로 - 당신은 처음에 한 번만 인쇄합니다. 이 두 가지 문제가 모두 발생합니다.

밑줄을 사용하여 "매개 변수 채우기"를 의미하는지 확인하십시오. 단 하나의 표현식 만 사용할 수 있습니다! 여러 문장을 사용하는 경우 명시 적으로 명명 된 매개 변수를 사용하는 것이 가장 좋습니다.

+0

와우, 재미 있고 시원하며 특별합니다! –

+0

뷰/스트림을 사용하여 스칼라가 한 번만 요소를 반복하지만 요소에 모든 함수를 적용하여 동일한 결과 (20)를 얻는 방법이 있습니까? 또는 코드를 다르게 작성해야합니까? –

+0

@ 존쉰 (JohnSmith) - 필터, 맵핑 및 리덕션은 전혀 다른 의미가 없으므로 쉽게 결합 할 수 없습니다. 물론 한 번 반복하여 필터링, 매핑 및 손으로 축소 할 수 있습니다. –

관련 문제