9.1 Reducing code duplication 
함수를 해부해 보면
공통부분: 해당 함수를 호출할 때 매번 같은 부분. 즉, 함수의 바디 
비공통부분: 함수호출마다 달라질 수 있는 부분. _function value_를 인자로 받을 경우, 이 _function value_를 비공통부분으로 볼 수 있음. 
 
 
higher-order function : 함수를 매개변수로 갖는 함수. 
다음 예제를 보자. 
 
object  FileMatcher  {
  private  def  filesHere  =  (new  java.io.File (" ." def  filesEnding (query : String ) = 
    for  (file <-  filesHere; if  file.getName.endsWith(query))
      yield  file
  def  filesContaining (query : String ) = 
    for  (file <-  filesHere; if  file.getName.contains(query))
      yield  file
  def  filesRegex (query : String ) =  
    for  (file <-  filesHere; if  file.getName.matches(query))
      yield  file
}object  FileMatcher  {
  private  def  filesHere  =  (new  java.io.File (" ." private  def  filesMatching (matcher : String  =>  Boolean ) = 
    for  (file <-  filesHere; if  matcher(file.getName))
      yield  file
  def  filesEnding (query : String ) = 
    filesMatching(_.endsWith(query))
  def  filesContaining (query : String ) = 
    filesMatching(_.contains(query))
  def  filesRegex (query : String ) =  
    filesMatching(_.matches(query))
}9.2 Simplifying client code 
API, library 등에 _higher order function_을 잘 사용하면 클라이언트 코드를 간결하게 만들 수 있다. 
 
def  containsNeg (nums : List [Int ]):  Boolean  =  {
  var  exists  =  false 
  for  (num <-  nums)
    if  (num <  0 )
      exists =  true 
  exists
}
//  다음처럼 higer order function을 활용할 수 있다def  containsNeg (nums : List [Int ]) =  nums.exists(_ <  0 )
currying : 복수의 인자 목록을 갖는 함수. 각 인자 목록은 ( )로 구분함 
 
def  curriedSum (x : Int )(y : Int ) =  x +  y
curriedSum(1 )(2 )
val  onePlus  =  curriedSum(1 )_  //  여기서 parameter list 전체를 치환하는 뒷부분 _ 앞의 공백은 생략할 수 있다. 앞 부분의 () 때문으로 보임. cf. println_ (X) <- println_ 자체가 유효한 식별자 이므로scala>  def  first (x : Int ) =  (y : Int ) =>  x +  y
first:  (x : Int )(Int ) =>  Int 
scala>  val  second  =  first(1 )
second:  (Int ) =>  Int  =  <function1 >
scala>  second(2 )
res6:  Int  =  3  9.4 Writing new control structures 
일등급 함수를 가진 언어에서는 새로운 제어구조를 만들 수 있다. 
 
scala>  def  twice (op : Double  =>  Double , x : Double ) =  op(op(x))
twice:  (op : (Double ) =>  Double , x : Double )Double 
scala>  twice(_ +  1 , 5 )
res9:  Double  =  7.0  
loan pattern: control abstraction 패턴으로 보임. 리소스를 인자 function에 '꿔 주는' 패턴. ex) 스트림을 열고 닫는 function / 열린 스트림을 전달받아 뭔가를 하는 function 
scala에선 하나의 parameter만 받을 땐 () 를 { } 로 바꿀 수 있음 
 
println(" Hello, world!" " 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
by-name parameter : 인자로 넘기는 함수가 인자를 갖지 않을 때 표현식이 어색해지는 문제를 해결해 줌. function 정의 시 ()를 명시하지 않으면 됨. 
 
def  noByName ( a : () =>  Boolean  ) =  a()
scala>  noByName( () =>  true  )  //  앞의 () => 가 보기싫다:  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하는 꼴.:  (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  
참고
 
by name parameter는 function을 넘기기 때문에 나중에 evalution되는 이점을 활용할 수 있음. 
 
currying과 by-name parameter는 control abstraction 구현에 도움을 준다.