복붙노트

[SCALA] 스칼라는 이상한 행동을 foreach는

SCALA

스칼라는 이상한 행동을 foreach는

나는 스칼라의 아름다운 한 - 라이너를 사용하여 값 목록을 반복하고 싶습니다.

예를 들어,이 사람은 잘 작동합니다 :

scala> val x = List(1,2,3,4)
x: List[Int] = List(1, 2, 3, 4)

scala> x foreach println
1
2
3
4

내가 자리 표시자를 사용 _하지만, 그것은 나에게 오류를 제공합니다 :

scala> x foreach println(_ + 1)
<console>:6: error: missing parameter type for expanded function ((x$1) =>x$1.$plus(1))
       x foreach println(_ + 1)
                         ^

왜 그런 겁니까? 여기에 입력 추론 컴파일러 수 없다?

해결법

  1. ==============================

    1.이:

    이:

    x foreach println(_ + 1)
    

    이 동일합니다 :

    x.foreach(println(x$1 => x$1 + 1))
    

    X $ 1 유형이 될 수 있으며, 솔직히 말해서,이 함수를 인쇄 할 수있는 이해가되지 않습니다에 대한 표시가 없습니다.

    (나에게) 분명히 대신, X $ 0하여 매개 변수를 foreach 문을 통과 할 경우 + 1 $ 0 x를 인쇄하는 것을 의미했다. 그러나,의이 ... foreach 문은 T는 목록의 형식 매개 변수 인 파라미터, 기능 1 [T, 단위]와 같은 소요 생각해 보자. 당신이 대신 foreach 문을 통과하는 것은에 println입니다 (_ + 1), 단위를 반환하는 식이다.

    당신이 쓴 경우, 대신에 X foreach 문에 println, 당신은 완전히 다른 일을 통과 할 것입니다. 당신은, 그러므로, foreach는의 요구 사항을 모든 소요 피팅 단위, 반환하는 기능 (*)에 println을 통과 할 것입니다.

    이는 _의 확장의 규칙 약간 혼란 가져옵니다. 일부 애플리케이션 기능 : 그것은 그들이 다른 것을 의미하는 경우 매개 변수의 위치에있는 경우를 제외하고, 최 식 분리 (괄호 또는 중괄호)으로 확장된다.

    이 더 잘 설명하기 위해 다음 예를 살펴 :

    def f(a: Int, b: Int, c: Int) = a + b + c
    val g: Int => Int = f(_, 2, 3) // Partial function application
    g(1)
    

    여기서는 F에 두 번째와 세 번째 인자를 적용하고 단지 나머지 논의를 필요로하는 기능을 반환. 그렇지 않으면 제가 적용되지 않은 인수의 유형을 표시해야 할 것, 그것은 단지 내가 g의 유형을 표시하기 때문입니다로 일합니다. 계속하자 :

    val h: Int => Int = _ + 1 // Anonymous function, expands to (x$1: Int => x$1 + 1)
    val i: Int => Int = (_ + 1) // Same thing, because the parenthesis are dropped here
    val j: Int => Int = 1 + (_ + 1) // doesn't work, because it expands to 1 + (x$1 => x$1 + 1), so it misses the type of `x$1`
    val k: Int => Int = 1 + ((_: Int) + 1) // doesn't work, because it expands to 1 + (x$1: Int => x$1 + 1), so you are adding a function to an `Int`, but this operation doesn't exist
    

    이것은 매우 중요한 점이기 때문에, 더 자세히 K 논의하자. g는 그 기능 지능 => INT, 권리 기억? 나는 1 + g를 입력했다 경우에 따라서, 그 말이 것인가? 즉 K에서 수행 된 것입니다.

    어떤 사람을 혼란스럽게하는 것은 그들이 정말 원하는 것은이었다입니다 :

    val j: Int => Int = x$1 => 1 + (x$1 + 1)
    

    즉, 그들은 _이 괄호 외부로 이동, 적절한 장소에하는 대체 X $ 1합니다. 여기서 문제는 그들에게 분명 보일 수도 있지만 적절한 위치가 무엇인지,이 컴파일러 명확하지 않다,이다. 예를 들어,이 예제를 생각해 봅시다 :

    def findKeywords(keywords: List[String], sentence: List[String]) = sentence.filter(keywords contains _.map(_.toLowerCase))
    

    우리는 괄호 외부에이 확장한다면 이제, 우리는이를 얻을 것입니다 :

    def findKeywords(keywords: List[String], sentence: List[String]) = (x$1, x$2) => sentence.filter(keywords contains x$1.map(x$2.toLowerCase))
    

    어떤 우리가 원하지 않는 것을 확실히한다. _가 가장 안쪽 식의 구분에 의해 제한되지 않은 경우 사실, 하나는 중첩 된지도, flatMap, 필터와 foreach는 함께 _ 사용하지 않을 수 있습니다.

    이제, 익명 함수와 부분 응용 프로그램 사이의 혼란, 이쪽을 봐 :

    List(1,2,3,4) foreach println(_) // doesn't work
    List(1,2,3,4) foreach (println(_)) // works
    List(1,2,3,4) foreach (println(_ + 1)) // doesn't work
    

    첫 번째 줄은 때문에 작동 표기법이 어떻게 작동하는지 작동하지 않습니다. 스칼라는 foreachexpects 것이 아니다 그에 println 반환 단위를 본다.

    괄호는 스칼라 전체에 println (_)을 평가 할 수 있기 때문에 두 번째 줄은 작동합니다. 그것은 부분적인 기능 프로그램이며, 그래서 허용 없음 => 유닛을 반환한다.

    세 번째 줄은 때문에 작동하지 않습니다 _ + 1 매개 변수에 println하는 당신이 전달하는 익명 함수입니다. 당신은 당신이 원하는 무엇 익명 함수,의에 println 부분을하지 않습니다.

    마지막으로, 몇 사람은 무엇을 기대 :

    List(1,2,3,4) foreach (Console println _ + 1)
    

    이 작동합니다. 이유는 독자에게 연습 문제로 남겨 않습니다. :-)

    (*) 사실에 println는 방법이다. 당신이 X의 foreach에 println 쓸 때 방법이 통과 할 수 없기 때문에, 당신은 방법을 전달하지 않습니다. 대신 스칼라는 폐쇄를 생성하고 전달합니다. 그것은 다음과 같이 확장 :

    x.foreach(new Function1[Any,Unit] { def apply(x$1: Any): Unit = Console.println(x$1) })
    
  2. ==============================

    2.밑줄은 약간 까다 롭습니다. 사양, 문구에 따르면 :

    밑줄은 약간 까다 롭습니다. 사양, 문구에 따르면 :

    _ + 1
    

    동등

    x => x + 1
    

    견딜 수 없는

    x foreach println (y => y + 1)
    

    수율 :

    <console>:6: error: missing parameter type
               x foreach println (y => y + 1)
    

    당신은 어떤 유형에 추가하는 경우 :

    x foreach( println((y:Int) => y + 1))
    <console>:6: error: type mismatch;
     found   : Unit
     required: (Int) => Unit
               x foreach( println((y:Int) => y + 1))
    

    문제는 당신이에 println하는 익명 함수를 통과하고 그것을 처리 할 수없는 점이다. 당신이 정말로 (당신이 목록에있는 각 항목의 후속를 인쇄 할 경우)하고 싶은 것입니다 :

    x map (_+1) foreach println
    
  3. ==============================

    3.

    scala> for(x <- List(1,2,3,4)) println(x + 1)
    2
    3
    4
    5
    
  4. ==============================

    4.밑줄 표현의 중첩 깊이에 대한 스칼라에서 이상한 제한이 있습니다. 이곳은 다음 예에서 볼 수있다 :

    밑줄 표현의 중첩 깊이에 대한 스칼라에서 이상한 제한이 있습니다. 이곳은 다음 예에서 볼 수있다 :

     scala> List(1) map(1+_)
     res3: List[Int] = List(2)
    
     scala> Some(1) map (1+(1+_))
     <console>:5: error: missing parameter type for expanded function ((x$1) => 1.+(x$1))
            Some(1) map (1+(1+_))
                         ^
    

    나에게 버그 것 같은데.

  5. ==============================

    5.

    Welcome to Scala version 2.8.0.Beta1-prerelease (Java HotSpot(TM) Client VM, Java 1.6.0_17).
    Type in expressions to have them evaluated.
    Type :help for more information.
    
    scala> val l1 = List(1, 2, 3)
    l1: List[Int] = List(1, 2, 3)
    
    scala>
    
    scala> l1.foreach(println(_))
    1
    2
    3
    
  6. from https://stackoverflow.com/questions/2173373/scala-foreach-strange-behaviour by cc-by-sa and MIT license