9장 control abstraction - codeport/scala GitHub Wiki

kingori


###9.1

function을 해부해 보면

  • common part: 해당 funciton을 호출할 때 매번 같은 부분. 즉, function의 body
  • non-common part: function 호출마다 달라질 수 있는 부분. function value를 인자로 받을 경우, 이 function value를 non-common part로 볼 수 있음.

higher-order function: function을 매개변수로 갖는 function. control abstraction을 가능케 하는 주인공!

###9.2

API, library 등에 higher order function을 잘 사용하면 client code를 간결하게 만들 수 있다. 끝.

###9.3

currying: 복수의 인자 목록을 갖는 function. 각 인자 목록은 ( ) 로 구분함

def curriedSum(x: Int)(y: Int) = x + y

val onePlus = curriedSum(1)_  // 여기서 parameter list 전체를 치환하는 뒷부분 _ 앞의 공백은 생략할 수 있다. 앞 부분의 () 때문으로 보임. cf. println_ (X) <- println_ 자체가 유효한 식별자 이므로

###9.4

loan pattern: control abstraction 패턴으로 보임. 리소스를 인자 function에 '꿔 주는' 패턴. ex) 스트림을 열고 닫는 function / 열린 스트림을 전달받아 뭔가를 하는 function

scala에선 하나의 parameter만 받을 땐 () 를 { } 로 바꿀 수 있음

println("Hello, world!" )
println { "Hello, world!" } //둘이 동일함

따라서 { } 로 뭔가 원래 문법틱하게 꾸미려면 single parameter만 받도록 구성해야 함. -> curring을 쓰면 됨 ==> 왠지 꼼수틱한데? 딱히 아래만 보면 별 차이가 없어보이긴 함.

def a( param1: Int, op: Int => Int ) = { op(param1) }
val b = a(3, _: Int => Int )
scala> b( _ * 2)
res9: Int = 6
scala> b { _ * 2 }
res10: Int = 6

def curr_a( param1: Int)(op: Int => Int ) = { op(param1) }
scala> curr_a(3) {  _ * 2 }
res11: Int = 6
scala> curr_a(3) { x => x * 2 }
res12: Int = 6
scala> val curr_b = curr_a(3)_
curr_b: Int => Int => Int = <function1>
scala> curr_b ( _ * 2 )
res13: Int = 6
scala> curr_b { _ * 2 }
res14: Int = 6

###9.5

by-name parameter: 인자로 넘기는 function이 argument을 갖지 않을 때 표현식이 어색해지는 문제를 해결해 줌. function 정의 시 () 를 명시하지 않으면 됨.

def noByName( a: () => Boolean ) = a()
scala> noByName( () => true )  // 앞의 () => 가 보기싫다
res16: Boolean = true
scala> noByName( true )
<console>:10: error: type mismatch;
 found   : Boolean(true)
 required: () => Boolean
              noByName( true )

scala> def byName( a:  => Boolean ) = a()
<console>:8: error: Boolean does not take parameters
       def byName( a:  => Boolean ) = a()
                                       ^
scala> def byName( a:  => Boolean ) = a
byName: (a: => Boolean)Boolean
scala> byName( true )
res18: Boolean = true

만약 이렇게 하면?

scala> def noByName( a: () => Boolean ) = a  // a만 도로 return하는 꼴.
noByName: (a: () => Boolean)() => Boolean
scala> noByName( true )
<console>:10: error: type mismatch;
 found   : Boolean(true)
 required: () => Boolean
              noByName( true )
                        ^
scala> noByName( () => true )
res24: () => Boolean = <function0>
scala> noByName( () => true )()
res25: Boolean = true

http://daily-scala.blogspot.com/2009/12/by-name-parameter-to-function.html

질문 : 178pg, by-name type 은 뭔 소리인가?

by name parameter는 function을 넘기기 때문에 나중에 evalution되는 이점을 활용할 수 있음.

###9.6

currying과 by-name parameter는 control abstraction 구현에 도움을 준다.

⚠️ **GitHub.com Fallback** ⚠️