첫 슬라이드는 다음과 같습니다. 뭔가 어려워보이죠? 각종 _ 의 용법은 모두 들어가 있습니다.
아주 간단하게 설명하면 아래의 offset 에 대입되는 커링 함수 sum2(count) 에서 count는 매번 실행시의 count 값이 바인딩됩니다.(악 벌써 여기부터 어려워!!!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Underscores { import collection.{ Map = > _ , _ } var count : Int = _ def sum = ( _: Int) + ( _: Int) def sum 2 (a : Int)(b : Int) = a+b def offset = sum 2 (count) _ def sizeOf(l : Traversable[ _ ]) : Unit = l match { case it : Iterable[Int] = > count = ( 0 / : it)( _ + _ ) case s : Seq[ _ ] = > s.foreach( _ = > count = count + 1 ) case _ = > println(offset(l.size)) } } |
두번째 슬라이드는 각각 어떤 용법으로 이루어졌나를 보여줍니다. 총 6가지 용법을 색상까지 이쁘게 보여주네요.
세번째 슬라이드 부터 각각의 용법에 대해서 알려줍니다.
1번은 “모두”를 의미합니다. 아래의 예에서 첫번째 Map => _ 는 일단 무시하시고(5번이니깐요.)
그 뒤의 _ 가 자바에서의 import * 와 같은 용법입니다.(왜 *가 아닌지는…)
1 | import collection.{ Map = > _ , _ } |
실제 예는 다음과 같습니다.
1 2 3 4 5 6 7 | import java.util. _ val date = new Date() import scala.util.control.Breaks. _ breakable { for (i <- 0 to 10 ) { if (i == 5 ) break } } |
웬지 breakable은 Exception을 잡아서 나가는 것 같은 느낌이 진하게 납니다.
2번은 디폴트 값 지정입니다. 숫자면 0 문자면 null로 지정됩니다.
1 | var count : Int = _ |
다만 이렇게 지정하는 건 생성자에서만 되고 함수안에서는 되지 않습니다.
1 2 3 4 5 6 7 8 | class Foo { var i : Int = _ // i = 0 var s : String = _ // s = null def f { // var i:String = _//error: local variables must be initialized } } |
3번째는 unused variables 입니다. 아래와 같이 _로 받은걸 쓰지 않게 되는 겁니다.
1 | case _ = > println(offset(l.size)) |
예를 보면 다음과 같습니다. 아래의 두 예는 같은 예입니다. x를 파라매터로 받지만… 쓰지 않는 겁니다.
1 2 | ( 1 to 5 ) foreach { (x : Int) = > println( "one more" )} ( 1 to 5 ) foreach { _ = > println( "one more" )} |
다음 예제들도 동일합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | def inPatternMatching 1 (s : String) { s match { case "foo" = > println( "foo !" ) case x = > println( "not foo" ) } } def inPatternMatching 2 (s : String) { s match { case "foo" = > println( "foo !" ) case _ = > println( "not foo" ) } } |
4번째는 이름 없는 파라매터입니다. 아주 명확하게 들어갈 변수 대신에 지정되게 됩니다.(3번하고는 반대입죠.)
아래의 예는 1…10 까지가 x로 바인딩되는데, 이걸 _로 대체하는 경우입니다. 명시적으로 사용하기 위해서이죠.
1 2 3 4 5 | ( 1 to 10 ) map { x = > x + 1 } ( 1 to 10 ) map { _ + 1 } ( 1 to 10 ).foldLeft( 0 ) { (x,y) = > x+y } ( 1 to 10 ).foldLeft( 0 ) { _ + _ } |
이제 partial function 에서 보면 더더욱 눈이 휘둥굴해 집니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | def f(i : Int) : String = i.toString def g = (x : Int) = > f(x) def g 2 = f _ def f 2 = ( _: String).toString def u(i : Int)(d : Double) : String = i.toString + d.toString def v = u _ def w 1 = u( 4 ) _ def w 2 = u( _: Int) 2.0 ) |
5번은 아까 Map 관련 헤더들을 import 하지 말라는 뜻입니다.
6번은 c++의 Template 처럼 특정 타입을 지칭하는 것입니다. 위에서 넘어온 타입을 그대로 사용하겠다라고 하면 이해가 쉬울까요.
다시 한번 말씀드리지만, 슬라이드가 잘 되어있으니, 실제로 보시면 꽤 도움이 되실껍니다. 뭐, 저도 공부하는 중이라…
'개발 > SCALA' 카테고리의 다른 글
Case class [펌] (0) | 2017.07.25 |
---|---|
함수형 프로그래밍 [펌] (0) | 2017.04.19 |
댓글