Welcome to F#(10) - 인도음식 카레.....?

F# 2009. 7. 3. 13:39 Posted by 알 수 없는 사용자

- 카레랑 F#이랑 뭔 상관이야.

우리나라말로 카레. 영어로 curry인거죠. F#에선(함수형 언어에선) 카레를 맛보실 수 있습니다. 음미하고 먹으려면 좀 복잡한 과정을 거쳐야 할지도 모르지만요. 그래서 기꺼이 드셔보시고자 하시는 분들. 어떻게 먹는지 천천히 이야기 해보시죠 캬캬캬캬캬...


- 모야 먹는거 아니자나+_+

Curry는 수학과 컴퓨터과학에서 사용되는 특정한 기술을 가리키는 말로서, 미국의 수리논리학자였던 Haskell Brooks Curry의 이름을 따서 지어졌다고 합니다. Haskell이라는 언어도 Haskell Brooks Curry의 이름을 따서 만들어졌죠. Curry는 함수형 프로그래밍의 기초를 쌓았던 사람중의 한명이라고 합니다. 아마도 그래서 함수형언어중에 그의 이름을 딴 언어와 기능이 있는것 같습니다.

Curry의 사후에 새로만들 언어의 이름을 Haskell로 하기로 정하고 그의 미망인에게 가서 언어의 이름을 Haskell로 정해도 좋겠냐고 하자 흔쾌히 허락하면서도 그가 한번도 Haskell이라는 이름을 좋아한 적이 없었다고 말했다는 군요. 본인이 좋아했든 안했든 Haskell과 Curry라는 이름은 프로그래밍언어의 역사속에서 영원히 기억되겠죠. 아... 행복한 사람이구만 ㅋㅋㅋ. 완전 부럽네. -_- 

어쨌든 currying은 "다수개의 인자를 받는 함수를 하나의 인자를 받는 함수로 만들고 나머지 인자를 받는 함수를 리턴하는 변환의 절차"라고 합니다. 무슨 말인지 이해가 가시나요? 음-_-;; 간단히 알아보도록 하죠. 


위의 그림을 보시면, 우선 add라는 인자 두개를 받아서 더한 결과를 리턴하는 함수를 선언한 걸 보실 수 있습니다. 즉, "add 3 5" 같은 형태로 사용하는거 겠죠. 하지만, currying을 하게되면, 다수개의 인자(a, b 두개)를 받는 함수(add)를 하나의 인자(a)를 받는 함수로 만들고 나머지 인자(b)를 받는 함수를 리턴하게 할 수 있습니다. 다음 그림이 바로 그 내용이죠. 


보시면 add5는 add 5의 결과, 즉 "add a b"에서 a에 5를 넣은 "add 5 b"를 가리키게 됩니다. 즉, 커리의 정의에 따르면, add5는 여러개의 인자를 받는 함수(add)를 하나의 인자를 받는 함수로 변환해서(add 5) 나머지 인자를 받는 함수를 리턴합니다.

위 사진에서 add5의 타입을 보시면, (int -> int), int하나를 받아서 int를 리턴하는 함수임을 보여주고 있습니다. 하지만 add5는 받는 인자가 없습니다. 즉, "add 5 b"에서 인자 하나를 제외한 나머지 b를 add5가 인자로 받아서 5 + b의 결과를 리턴하는 함수라는 말이죠. 


그리고 result에 "add5 10"의 결과를 대입합니다. 그 결과는 add함수의 나머지 하나의 파라미터에 10을 집어넣은 즉, 5 + 10의 결과값인 15가 들어가겠죠.

 

 

위 그림에서 그 결과를 확인하실 수 있습니다. 위의 단계들을 그림으로 설명해보면 아래와 같습니다.

 

 

그리고 실제로 생성되는 IL코드를 통해서도 한번 확인해보도록 하겠습니다.

 

 

빌드한 코드를 ildasm을 통해서 보고있는건데요. 신기한건, add5가 클래스의 형태로 되어있다는 겁니다. ".ctor"은 생성자를 의미하죠. 그리고 멤버변수로 a가 들어가 있습니다. "add5 = add 5"가 클래스의 형태로 만들어지고 5는 멤버변수로 저장되어 있다가 나중에 호출될때 사용되는거 같군요. 그러면 add5의 호출부분인 Invoke쪽을 보겠습니다.

 

 

빨간박스로 표시된 부분을 위에서 부터 차례대로 보시면 add5는 "b"라는 int32형 인자를 하나 받아서 호출됩니다. 그리고 멤버변수인 a를 로드하구요, 그 둘을 가지고 add메서드를 호출합니다. 그렇습니다. 내부적으로는 이렇게 처리를 하는군요.

제가 왜 이렇게 curry에 대해서 설명을 드리는고 하니, 바로 F#의 기반에 그 curry가 깔려있기 때문이죠. 아래의 그림에서 뭔가 이상한걸 느끼셨다면, 바로 그게 curry입니다.

 

 

즉, "->'이게 들어가있으면 함수라는 이야기 인데, "add a = a + 5"같은 함수라면, 아... 이게 정수를 하나받아서 거기에 5를 더한 정수를 하나 리턴하는 구나.... 해서 "int -> int"라는게 이해가 되는데, 어째서 "add a b = a + b"는 "int -> int -> int"일까요? 그렇습니다. 내부적으로 curry를 사용하고 있기 때문입니다.

즉, "add 3 5"라고 해주더라도 curry를 통해서 "add 3 "을 통해서 3을 인자로 받고 정수형 인자 하나를 받는 함수를 리턴합니다. 그리고 그 함수에 5를 넘겨줘서 결과값인 8을 얻게 됩니다. 그래서 int를 받아서 "int -> int"인 함수를 리턴하고, 그 "int -> int"인 함수에 다시 int를 하나 넘겨줘서 결과로 int를 받는거죠. 이번에도 그림으로 정리해보면 아래와 같습니다.(별 도움이 안되는거 같지만 정성을 생각해서 자비좀....-_- ㅋㅋㅋ)

 

 

- 정리하며

넵, 오늘은 curry에 대해서 알아봤습니다. 충분히 설명을 못드린거 같아서 좀 불편한 마음이 있군요. 모든건 제 책임이니 저에게 따스한 격려를(?)....... 암튼, 이렇게 curry를 이용하게 되면, 위에서 보셨듯이 하나의 함수에서 새로운 함수들을 계속 해서 만들어 낼 수 있고, 그렇게 함수를 프로그램을 만들어가는 building block으로 사용할 수 있습니다. 더 구체적인 예를 드리지 못해서 아쉽군요. 더 공부해서 내공이 허락한다면 더 설명드리도록 하겠습니다.

 

- 참고자료

1. http://geekswithblogs.net/Podwysocki/archive/2008/02/21/119880.aspx
2. http://diditwith.net/2007/08/15/TheArtOfCurrying.aspx
3. http://www.dotnetrocks.com/default.aspx?showNum=310