정적 타이핑과 동적 타이핑

Posted 2008/03/28 02:54
마이크로소프트의 IronRuby 팀에서 No Borg-like release train for Ruby on .NET 이라는 글을 통해 올해 말까지는 IronRuby 1.0을 완성하겠다는 발표를 했습니다. 루비가 제대로 된 언어 명세도 없다보니 명확한 시멘틱이 정의가 안 된 부분이 많고 구현마다 다른 부분을 어려움으로 호소하고 있습니다. 아 그리고 루비의 가장 중요한 어플리케이션이 Rails인 만큼 IronRuby on Rails도 중요하게 생각하고 있는 것 같습니다.

그런데 이 글의 마지막 문구에서 왜 .NET 개발자가 루비에 관심을 가져야 하느냐는 질문에 Iron Ruby 프로젝트 리더인 John Lam 말이 정적 타이핑(static typing)하는 언어는 동적 타이핑(dynamic typing)하는 언어보다 유지보수 하기가 힘들다는 말을 했습니다. 유지 보수가 힘든 이유는 변경이 힘들기 때문이라고 이야기했습니다.


Finally, why should .NET developers bother with Ruby? According to Lam: "You spend less time writing software than you spend maintaining software. Optimizing for writing software versus maintaining software is probably the wrong thing to do. Static typing makes it harder to maintain software because it's harder to change it."®


저는 정반대로 생각하기 때문에 순간 글을 잘못 읽었나 착각에 빠졌습니다. 이와 관련해  Haskell Cafe에도 Dynamic typing makes you more productive? 라는 글에 내용이 올라오면서 많은 사람들이 자기 생각을 달았습니다. 요약하면, C++, Java, C# 처럼 어설픈 정적 타이핑하는 언어를 보던 사람들에게는 루비의 동적 타이핑이 굉장한 장점으로 보일 수 있는 것은 사실입니다만 제대로 된 정적 타이핑을 하는 언어를 보면 그런 생각을 바꿀 것이라는 의견입니다. 물론 헤스켈 커뮤니티 메일링 리스트니깐 당연히 그렇게 이야기하겠지만요.

결론: 정적 타이핑의 이름을 더럽힌 자바랑 C# 나빠요.

헤스켈과 병렬 프로그래밍

Posted 2008/03/26 02:25
제가 함수형 언어에 직접적인 관심을 가지게 된 계기는 함수형 언어가 멀티코어 프로그래밍(병렬 프로그래밍)에 대한 가장 활발한 연구 결과를 내어놓고 있기 때문입니다. 부작용(side-effect)이 없고 연산(evaluation) 순서에 제약이 덜하다는 함수 언어 자체의 특징이 병렬화와 잘 어울리는 부분도 있습니다만, 언어 특징과 별개로 병렬 프로그래밍에 대한 최신 생각들이 함수 언어에 가장 먼저 적용되는 부분도 무시할 수 없습니다.

병렬 프로그래밍하면 주로 얼랑(Erlang)이 많이 주목받고 있습니다. 함수 언어 중 거의 유일하게 상업적인 용도로 이용된 적이 있다는 사실 때문에 근래에 관심을 가지게 되신 분이 많이 있는것 같습니다. 하지만 경량 프로세스(lightweight process)와 메시지 패싱 방식은 순차적 프로그래밍에 익숙한 기존 개발자들이 쉽게 적응할 수 있는 모델이 아니라 굉장히 큰 진입 장벽이 존재합니다. 자바 개발자가 파이썬으로 코딩해도 여전히 자바 스타일인 것처럼 락 기반 멀티쓰레드 프로그래밍에 익숙한 개발자가 태스크를 잘게 쪼개고 수많은 경량 프로세스를 통해 메시지를 주고 받는 모델로 개발하기란 쉽지 않습니다.

더불어 얼랑은 함수 언어 연구와 깊은 상관관계를 맺고 있는 정적 타입 시스템의 장점을 전혀 살리지 못하는 동적인 언어라는 사실도 약점입니다. 얼랑이 주로 통신 장비 등 상당한 안정성이 요구되는 분야에 사용된 언어임에도 불구하고, 버그를 일찍 쉽게 발견할 수 있게 도와주는 정적 타입 시스템의 도움을 전혀 못 받고 있다는 사실을 조금 의외입니다. 런타임에 쉽게 오류에서 회복되는 것도 중요하지만 애당초 버그를 줄일 수 있었다는 더 좋았을 텐데 말이죠.

헤스켈은 병렬 프로그래밍과 관련해서는 가장 많은 옵션을 제공하는 언어입니다. 일단 가장 유명한 세 가지는 다음과 같습니다.


1) Concurrent Haskell

forkIO 등의 함수를 이용해 쓰레드를 생성하고 죽일 수 있으며 MVar 등 공유 메모리를 이용해 동기화하는 모델입니다.

2) Parallel Haskell

Paralle Haskell은 `par`와 `seq` 등을 이용해 순차적인 프로그램에 병렬화할 수 있는 단서를 달아주는 방법입니다. 어떤 부분이 동시에 수행될 수 있는지만 알려주면 헤스켈이 알아서 쓰레드를 생성하고 동기화를 해줍니다. 아래 글을 참고하세요.

3) Software Transaction Memory

1) 번 모델을 발전시킨 것으로 데이터베이스의 트랜잭션처럼 특정 코드를 모 아니면 도(all or nothing)로 실행시켜주는 방법입니다. 직접 메모리에 쓰는 대신에 트랜잭션 로그를 만들고 한 번에 커밋하는 방식입니다. 도중에 누가 방해하면 처음부터 다시 실행하면 됩니다. retry를 이용해 컨디션 변수를 대신해 블로킹을 할 수도 있습니다.

락 기반 멀티쓰레드 프로그래밍의 문제점인 데드락, 레이스컨디션 등이 불가능하고, 규모 가변성(scalability)이 뛰어난 편이라 병렬 프로그래밍 계의 총아로 떠오르고 있는 분야입니다.

Monad tutorials timeline

Posted 2008/03/19 02:34
4월 마소 원고 주제를 헤스켈을 이용한 STM(Software Transaction Memory)으로 잡고 마무리를 하고 있습니다.

지금은 모나드(monad)에 대한 설명을 추가하려고 모나드 튜토리얼을 좀 찾아보고 있었습니다. 모나드는 추상적인 개념이다보니 헤스켈 입문자들이 가장 어려워 하는 부분이기도 하고 깊이 있게 이해하기가 쉽지 않은 부분입니다. 과거에는 찾아볼 자료도 별로 없었는데 최근에 헤스켈 개발자가 늘고 있어서 그런지 2006, 2007년도에 모나드 관련 글이 굉장히 많이 나왔더군요. Monad tutorials timeline에 보시면 모나드 튜토리얼이 시대별로 어떻게 변천해 왔는지도 보실 수 있습니다.

튜토리얼에는(혹은 튜토리얼이기 때문에) 보통 모나드의 이론적인 배경인 카테고리 이론(category theory)과의 연관 관계를 설명하는 부분이 빠져 있어서 살짝 아쉽네요.

A taste of Haskell

Posted 2008/03/18 03:17
Simon Peyton-Jones가 2007년 OSCON에서 발표한 A taste of Haskell 발표를 봤습니다. 함수형 언어 Haskell을 소개하는 자리인데 1편, 2편 각각 90분씩 총 3시간의 분량으로 비함수형 프로그래머들에게 함수형 언어의 장점과 특징을 소개하고 있습니다. 슬라이드도 여기에서 보실 수 있습니다.

xmonad라는 X 윈도용 윈도 매니저 프로그램을 이용해 함수형 언어에서 간과하기 쉬운 IO 사용이나 외부 함수(foreign function) 호출 등도 다루고 있습니다.

사용자 삽입 이미지

참고로 SPJ 이 분은 GHC(Glasgow Haskell Compiler)를 비롯해 함수형 언어 이론 및 구현에 많은 업적을 남기신 분입니다. 함수형 언어의 실무와 이론을 모두 해본 사람으로 함수형 언어에 대해 누구보다도 열정이 강하고 할 말이 많은 사람이기도 합니다.

이쪽 분야에 관심을 가지면서 보니 참 똑똑한 사람들이 많더군요 ㅠ.ㅠ







뱀다리: OSCON 하니깐 생각나는데 까멜레오 프로젝트도 올해 3월 OSCON에서 발표를 신청했었습니다. 영어로 열심히 설명을 적었는데, 아직 오픈소스를 못하고 있어서 참가 여부가 매우 불투명한 상태라서 문제이지만요.

Using Haskell from Python with ctypes

Posted 2007/08/07 03:01
Recently, I am trying to make it possible to write Chameleo plugins in Haskell. Chameleo is wirtten mostly in Python and there is no direct method to call Haskell functions in Python. However, Python is the most powerful glue language in the world(Okay, maybe next to Perl), it is not hard to use both Haskell and Python at the same time within an application. PythonVsHaskell shows an example which compiles the Haskell code with ghc and generates a dll file. Python ctypes can call these functions in the DLL as if they are normal C functions.

MissingPy seems to be another option for calling Python code from Haskell (but not calling Haskell code from Python). The recent version is 0.8.9, but it seems to be still in beta quality.
Dynamic Typing과 관련된 글을 블로그에 Static Type Checking이란 제목으로 쓴 적이 있는데 여기서 다시 한 번 정리해 보고자 한다.

블로그를 돌아다니다보면 많은 사람들이 TDD가 Dynamic Typing하는 언어의 특징이라고 생각하고 있음을 알 수 있다. 특히 일부 파이썬/루비 팬들이 운영하는 블로그에서 TDD가 언급되면 어김없이 동적 타이핑 언어의 테스트 편리성(혹은 크게는 생산성)에 대한 이야기가 뒤따라 온다.

하지만 C/C++처럼 수십 년도 더 된 구세대 언어와, 소프트웨어 개발 방법론과 테스팅에 대한 어느정도 이해가 쌓인 후에 나온 파이썬/루비와 같은 언어를 정적/동적 타이핑 면에서만 놓고 비교하는 것은 공정하지 못한다. 사실 너무 불공평하다.

파이썬/루비와 정반대 선상에서 정적 타입핑의 극상을 달리는 친구들은 ML과 Haskell 같은 함수형 언어(functional)들인데, 이 놈들은 C/C++ 보다 더 엄격하게 컴파일 타임에 타입 검사를 한다. 하지만 이쪽 언어 사용자들의 주장에 따르면 ML과 Haskell은 절대 테스트하기 불편한 언어도 아니고, 코드 길이가 길거나 생산성이 떨어지는 언어도 아니다.

순수하게 타이핑 측면에서만 바라본다면, 동적 타이핑은 컴파일 타임에 해주는 검사가 적은만큼(상당히 귀납적이다) 테스트를 통해 더 많은 버그를 찾아내야 하므로, 테스트를 훨씬 더 철저하게 많이 해야 한다. 잘못된 타입 연산 등의 간단한 버그 조차도 테스트를 통해서만 발견할 수 있다는 것은 재앙이다(타입 검사는 연역적이다)

테스트의 부담이 더 큰 파이썬/루비 같은 동적 타이핑 언어가 테스트를 강조하는 것은 당연한 일이다. 같은 기능을 하는 다른 프로그램 보다 더 많은 테스트를 해야 프로그램이 제대로 동작하기 때문이다. 즉 원래 언어적인 측면에서 태생적인 약점이 있으므로, 후천적인 노력으로 개선을 한 셈이다.

파이썬과 루비 같은 동적 타이핑하는 스크립트 언어의 테스트 편리성은 동적 타이핑이라는 속성에 기인한 것이 아니다. 이는 언어의 추상화(abstraction) 수준과 관계가 있다. 추상화 수준이 높을수록 코드는 사람이 생각한 바(스펙)에 가까워지고, 알아보기 쉬워지며, 금방 만들 수 있다.

C 언어와 파이썬/루비의 추상화 수준은 어떻게 다를까? 간단한 통계로 C 언어 construct 하나가 보통 1-10개의 머신 인스트럭션으로 컴파일 되는 반면에, 파이썬과 루비의 construct 하나는 100-1000개 이상의 머신 인스트럭션으로 실행된다.

즉, 파이썬이나 루비 개발자가 그토록 강조하는 "가독성", "짧은 코드"는 절대로 동적 타이핑(흔히 스크립트 언어)의 특성이 아닌 셈이다. 강력한 정적 타이핑 언어인 헤스켈(Haskell)의 퀵 소트 코드를 본 적이 있다면, 타이핑은 생산성이나 테스트 편의와는 직접적인 상관 관계가 없다는 데 동의할 것이다.

qsort [] = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)

위 Haskell 코드는 polymorphic하다. qsort에 넘길 수 있는 타입은 >= 연산자가 정의된 list이기만 하면 된다. Haskell이 이처럼 간결한 코드를 보여줄 수 있는 이유는 파이썬/루비와 같은 수준의 추상화 레벨이면서, type inference를 통해 불필요한 타입 어노테이션을 필요를 상당히 줄였기 때문이다.

이처럼 같은 추상화 수준이라면 당연히 동적 타이핑보다는 정적 타이핑이 유리하다. 비유하자면, 타입 이론은 '사람은 모두 죽는다' '그러므로 소크라테스도 죽는다'라고 말하는 것이고, 테스트는 'A도 죽었고, B도 죽었고, C도 죽었으니 아마 소크라테스도 죽을 것이다'라고 말하는 셈이다.