[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.이:
이:
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.밑줄은 약간 까다 롭습니다. 사양, 문구에 따르면 :
밑줄은 약간 까다 롭습니다. 사양, 문구에 따르면 :
_ + 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.
scala> for(x <- List(1,2,3,4)) println(x + 1) 2 3 4 5
-
==============================
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.
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
from https://stackoverflow.com/questions/2173373/scala-foreach-strange-behaviour by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] org.apache.spark.sql.Dataset에서 java.lang.NullPointerException이 :에 의해 발생 (0) | 2019.10.31 |
---|---|
[SCALA] 왜 사용자 정의 케이스 클래스의 데이터 집합을 만들 때 "데이터 집합에 저장 유형에 대한 인코더를 찾을 수 없습니다"인가? (0) | 2019.10.31 |
[SCALA] 스칼라 형 ascriptions의 목적은 무엇인가? (0) | 2019.10.31 |
[SCALA] 스칼라 생성자 매개 변수의 기본 개인 발을합니까? (0) | 2019.10.31 |
[SCALA] 어떻게 SBT 자식에서 종속 아티팩트를 당겨 수 있습니까? (0) | 2019.10.31 |