일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Akka
- 그라파나
- Adapter 패턴
- 파이썬 동시성
- Play2 로 웹 개발
- 스칼라 강좌
- 스위프트
- 파이썬 데이터분석
- Hyperledger fabric gossip protocol
- 이더리움
- 플레이프레임워크
- akka 강좌
- 파이썬 머신러닝
- Golang
- 스칼라
- 블록체인
- hyperledger fabric
- Play2
- 스칼라 동시성
- Actor
- 하이브리드앱
- play2 강좌
- 파이썬 강좌
- 엔터프라이즈 블록체인
- CORDA
- 하이퍼레저 패브릭
- 파이썬
- play 강좌
- 주키퍼
- 안드로이드 웹뷰
- Today
- Total
HAMA 블로그
스칼라 강좌 (28) - Currying(커링) 본문
* 참고로 커링이 무엇인가요에 대한 대답은 너무 쉽다. 하지만 왜 커링이 그렇게 유용하나요? 에 대한 대답은 아직 못얻었다. 뇌 로는 알겠지만 체득하지 못한 상태. 스칼라를 함수형 파라다임으로 사용을 많이 해봐야 알게 되지 않을까..
스칼라에서의 커링 (currying)
1. 개념
스칼라 Doc 에서는 이렇게 말합니다. (http://docs.scala-lang.org/ko/tutorials/tour/currying)
메소드에는 파라미터 목록을 여럿 정의할 수 있다. 파라미터 목록의 수 보다 적은 파라미터로 메소드가 호출되면, 해당 함수는 누락된 파라미터 목록을 인수로 받는 새로운 함수를 만든다.
중요한 포인트를 뽑아내어 쉽게 설명해보면
매우 쉬운 설명
- 메소드라는건 파라미터를 가지고 있지요? 예를들어 add( int x , int y) 이렇게 2개를 가지고 있을때
- add 라는 메소드를 호출 할 때 인자 2개를 넣어주지 않으면 보통 에러 나잖습니까?
- 근데 하나만 넣어도 에러가 나지 않는데다가 ~~ 즉 add (10) 이렇게 해두 되고
- 누락된 파라미터 만을 사용하는 새로운 메소드를 만들어 준 답니다.~ 즉 add(int y) 라는 새 메소드말이죠.
- add (int y) 라는 새 메소드는 나중에 호출 할 수 있는데 그 때 이전에 넣어 둔 10이 암시적으로 작용됩니다.
슈도코드로 살짝 보면
int add (int x, int y) {
return x + y;
}
원래 이런 함수인데
add (10) 이렇게 호출하면 add(int y) 라는 메소드가 만들어지며 , 10은 새 메소드에 저장되어 있게 됩니다.
int add( int y) {
return 10 + y;
}
즉 이런 함수가 자동으로 만들어 진 다는 말이지요.
이 함수를 add(5) 호출하면 결과로 이전에 입력된 10을 더하여 15가 리턴됩니다.
2. 스칼라 예제
object CurryTest extends App {
def filter(xs: List[Int], p: Int => Boolean): List[Int] =
if (xs.isEmpty) xs
else if (p(xs.head)) xs.head :: filter(xs.tail, p)
else filter(xs.tail, p)
def modN(n: Int)(x: Int) = ((x % n) == 0)
val nums = List(1, 2, 3, 4, 5, 6, 7, 8)
println(filter(nums, modN(2)))
println(filter(nums, modN(3)))
}
위의 스칼라 예제의 modN(n: Int)(x: Int) 가 커링되는 함수입니다.
보시다시피 modN(n: Int)(x: Int) 는 2개의 파라미터를 넣어야하는 함수입죠..
위에서 설명했다시피 이걸 파라미터 하나만 넣어서 호출 할 수 도 있으며 그렇게 하면 새로운 함수가 만들어진답니다.. 즉 modN(2) 이렇게 호출 했더니 에러는 안나고 대신 새로운 함수를 만들어서
def filter(xs: List[Int], p: Int => Boolean) filter 파라미터 p로 넣어주고 있습니다.
위의 p 파라미터 자리에는 modN(2) 를 호출해서 만들어진 새로운 함수가 들어 간다는 말입니다.
새로운 함수는 이렇게 생겼겠죠? (이미 2를 n 자리에 넣었다는것을 기억하시구요)
def modN(x: Int) = ((x % 2) == 0)
3. HOW?
여기에 하나의 함수를 파라미터로 받아서 , 그 함수를 내부에서 사용하고 2개의 Int 형을 받는 함수를 리턴하는 함수가 있습니다.
def sum(f:Int=>Int):(Int,Int)=>Int={
def sumF(a:Int,b:Int):Int=
if(a>b) 0 else f(a)+ sumF(a+1,b)
sumF
}
이런 경우 내부에 함수를 선언하지 않고 , 함수 파라미터 한개와 2개의 Int 형 파라미터 , 즉 3개의 파라미터를 받는 커링 함수를 아래처럼 만들수 도 있습니다.
def sum(f:Int=>Int)(a:Int,b:Int):Int=
if(a>b) 0 else f(a)+sum(f)(a+1,b)
4. {} 의 사용
스칼라에서는 함수호출시 () 대신 {} 중괄호를 사용 할 수 있다. 단 !!! 인재가 하나일 경우 !!
println ("Hello World") 대신해서 println { "Hello World" } 를 사용 할 수 있다는 의미이다.
스칼라에서 이렇게 한 이유는 클라이언트 프로그래머가 중괄호 내부에 함수 리터럴을 사용하도록 하기 위해서이다. 이렇게 작성한 메소드는 호출 시 좀 더 제어 추상화 구문과 비슷해진다.
def withPrintWriter(file: File, op: PrintWriter => Unit ) {
......
}
이런 함수를 호출 할 때는
withPrintWriter ( new File ("date.txt") ,
writer => writer.println(new java.util.Date) )
이렇게 할 수 있는데 , 인자가 2개이기 때문에 { } 를 사용할 수 없다.
하지만 !!!!
def withPrintWriter(file: File) (op: PrintWriter => Unit ) {
val writer = new PrintWriter(file)
try {
op (writer)
} finally {
writer.close()
}
}
이러한 함수라면 {} 를 사용가능하다.
val file = new File("date.txt")
withPrintWriter (file) {
writer => writer.println(new java.util.Date)
}
왜 그러냐면 커링을 통해서 file 을 매개변수로 먼저 넣은 새로운 함수가 생겨졌고,
그 새로운 함수는 매개변수 하나를 필요로 하는 함수이기 때문이다.
보통 (변수,함수) 매개변수 조합일 때 많이 사용된다.
def foldLeft[B](z: B)(op: (B, A) => B): B = {
var result = z
this foreach (x => result = op(result, x))
result
}
Vector(1, 2, 3).foldLeft(Vector[Int]()) { (is, i) =>
is :+ i * i
}
5. 추가 읽을거리 : Partial function 과의 차이
함수 인자를 생략하는 문법들에는
- 디폴트파라미터
- implicit
- partial applied function
- currying
등 이 있는데 그 중에 헤깔리기 쉬운 currying vs partial function 에 대해 살펴보자. 아래 링크를 읽으심이
http://www.vasinov.com/blog/on-currying-and-partial-function-application/
'Scala' 카테고리의 다른 글
스칼라 강좌 (30) - type projection ( # 에 관하여) (0) | 2016.12.06 |
---|---|
스칼라 강좌 (29) - for comprehensions (0) | 2016.11.12 |
스칼라 강좌 (27) - 모나드 (Monad) (0) | 2016.11.08 |
스칼라 강좌 (26) - JSON 다루기 (0) | 2016.10.19 |
스칼라 강좌 (25) - 부분 함수 (Partial function) (0) | 2016.10.03 |