부분 적용 함수(partially applied function)에 대한 예시이다. 마치 함수처럼 사용할 수 있다. 


def test(s1: String)(s2: String) = s1 + s2
val a = test("s1")
println(a)

이렇게 하면 에러가 발생한다.


Error:(10, 15) missing argument list for method test in object Main

Unapplied methods are only converted to functions when a function type is expected.

You can make this conversion explicit by writing `test _` or `test(_)(_)` instead of `test`.

  val a = test("s1")




에러가 발생하지 않도록 하려면 다음처럼 _를 추가해야 한다.

def test(s1: String)(s2: String) = s1 + s2
val a = test("s1") _
println(a)


실제 테스트 결과를 출력하면 다음과 같다.

def test(s1: String)(s2: String) = s1 + s2
val a = test("s1") _
println(a("s2"))


만약 매개변수가 3개라면 _(언더바)를 2개를 써야할까? 하나면 쓰면 된다. _는 나머지를 가르키는 대명사 역할을 한다.

def test(s1: String)(s2: String)(s3: String) = s1 + s2 + s3
val a = test("s1") _
println(a)


만약 다음과 같은 형태를 사용할 수 있다.

def test(s1: String) = (s2: String) => s1 + s2
val a = test("s1")
println(a)



언커링하려면 다음과 같다.

def test(s1: String, s2: String) = s1 + s2
val curried = (test _).curried
println(curried("s1")("s2"))
println(test("s1", "s2"))


결과는 다음과 같다.


s1s2

s1s2




curried함수는 Function2 트레이트의 함수로서 정의되어 있는 함수이다. 

/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2) == apply(x1, x2)`
*/
@annotation.unspecialized def curried: T1 => T2 => R = {
(x1: T1) => (x2: T2) => apply(x1, x2)


만약 커링함수를 언커링할 수 있다. 

val uncurried = Function.uncurried(curried)
println(uncurried("s1", "s2"))



함수와 콜렉션를 받는 함수라면 다음처럼 사용할 수 있다. 

object MyCombinator {
def foreach[A, U](f: A => U)(list: List[A]): Unit = list foreach f
}
val printX = (s: String) => println(s)
val f = MyCombinator.foreach(printX) _
f(List("1", "2"))

결과는 다음과 같다.


1

2








다음은 부분 함수이다. PartialFunction을 사용한다. 부분 적용 함수와 완전히 다른 형태이다. 입력 값이 일정 범위에 있는지를 정의할 수 있는 함수 정도(수학적인 부분을 의미하는지 알려주는 함수)가 될 것이다. 따라서 case 문으로 많이 사용된다. 

val one: PartialFunction[Int, String] = { case 1 => "one" }
println(one.isDefinedAt(1))
println(one.isDefinedAt(2))
println(one(1))


결과는 다음과 같다.


true

false





PartialFunction의 또 다른 예시이다. 

  val div: PartialFunction[(Double, Double), Double] = {
case (x, y) if y != 0 => x /y
}
println(div.isDefinedAt(1, 1))
println(div.isDefinedAt(2, 1))
println(div(1, 1))
}

결과는 다음과 같다.


true

true

1.0




PartialFunction는 case문 아니면 에러가 발생한다.  다음과 같은 코드에 컴파일 에러가 발생한다.

val one: PartialFunction[Int, String] = { "" }


Error:(9, 45) type mismatch;

 found   : String("")

 required: PartialFunction[Int,String]

  val one: PartialFunction[Int, String] = { "" }




항상 case 문이 있어야 하지만, 다음 코드는 컴파일 에러가 발생하지 않는다. 정의대로 구현했기 때문이다.

val one = new PartialFunction[Int, String] {
def apply(d: Int) = ""
def isDefinedAt(d: Int) = d != 0
}




PartialFunction 트레이트와 PartionFuction 오브젝트가 존재한다. 

trait PartialFunction[-A, +B] extends (A => B) { self =>
import PartialFunction._ ..

object PartialFunction {






참고로 PartialFunction은 예외를 발생하지 않는다.




    val f: PartialFunction[String, String] = { case "ping" => "pong"}


    val g: PartialFunction[List[Int], String] = {

      case Nil =>"one"

      case x :: rest =>

        rest match {

          case Nil => "two"

        }

    }




패턴매칭에 맞으면 true/false를 리턴한다. 


 println(Lists.f.isDefinedAt("ping"))

 println(Lists.g.isDefinedAt(List(1,2,3)))




'scala' 카테고리의 다른 글

[scala] for 내장  (0) 2016.12.08
[scala] try-catch/Try-match/Either/Validation  (0) 2016.12.06
[scala] 꼬리 재귀(tail recursion)와 @tailrec  (0) 2016.12.05
[scala] Future말고 Promise  (0) 2016.11.27
[scala] Future 2  (0) 2016.11.23
Posted by '김용환'
,