ML

스탠퍼드 대학교 인공지능 연구실에서 LCF 시스템을 성공적으로 완성한 밀너는 1973년에 에든버러 대학교의 교수로 임용되자 LCF를 개선하는 작업에 착수했다. 스탠퍼드 LCF 시스템에서 가장 문제가 되었던 것은 두 가지였다.

첫 번째는 메모리 용량의 제한으로 인해서 증명을 제대로 진행할 수 없는 경우가 생겼다. 두 번째는 사용자에게 제공되는 명령어를 확장하기가 어려웠다.

첫 번째 문제를 해결하기 위해서 밀너는 완료된 증명에 대해서는 중간 단계에서 생성된 정보를 모두 삭제했다. 스탠퍼드 LCF 시스템은 사용자가 프로그램을 종료할 때까지 그사이에 생성된 모든 정보를 저장했었다.

두 번째 문제는 ML(Meta Language)이라는 새로운 프로그래밍 언어를 통해 해결했다. 사용자는 이 언어로 새로운 명령어를 구현할 수 있었다. LCF 시스템을 위해 만들어진 ML은 타입 처리에 신경을 쓴 함수형 언어였고, 얼마 되지 않아 다른 용도로도 널리 쓰이게 되었다. 이 과정에서 사용자들은 각자의 용도에 맞게 조금씩 언어를 변형해서 사용했고, 그러다 보니 비슷하기는 하지만 조금씩 다른 ML 언어들이 혼란을 불러일으켰다. 그래서 1980년대 초반에 표준 제정에 대한 움직임이 시작되었고 1997년에 Standard ML 안정 버전이 공개되었다.

ML은 함수형 언어이기는 하지만 약간 변칙적이다. 함수형 언어는 함수의 호출로만 프로그램이 구성되기 때문에 대입문assignment이 필요하지 않다. 대입문은 어떤 값을 임시로 변수에 저장하게 되는데, 변수는 메모리 번지를 통해 접근이 가능하므로 프로그램 상의 오류나 실수로 인해 이 변수를 잘못 건드려서 예상치 못한 상황을 야기할 수 있다. 이를 부작용side-effect라고 부른다. 함수형 언어는 함수를 호출하고 그 결과값을 받아서 처리하는 동작으로만 구성되기 때문에 대입문이 필요 없고 따라서 부작용이 발생하지 않는다.

하지만 ML은 일반 수식 사용을 허용하고 여기에는 대입문도 포함되어 있다. 따라서 부작용이 발생할 가능성이 존재한다.

다음은 초기 ML 언어의 사용 예이다.

letrec scalarprod ($*, $+, zero)(l1, l2) =
( let x1.l1' = l1 and x2.l2' = l2
  in (x1*x2) + scalarprod($*, $+, zero)(l1', l2')
) ?
( if null(l1) & null(l2) then zero
                         else fail)

letrec는 재귀함수임을 나타내는 지정어이다. scalarprod가 이 재귀함수의 이름이다. 이 함수는 인자들을 2단계에 걸쳐서 받는다. 처음 나오는 인자들 $*, $+, zero는 연산자와 상수인데, 실행 과정에서 이 함수를 호출하는 코드에 의해 결정될 수 있다. $는 이 연산자가 binary infix임을 나타낸다. 그 다음에 나오는 인자인 l1, l2에는 이 함수가 실제로 적용될 데이터가 담긴다.

let은 수식을 정의하는데 사용한다. 이때 이 수식의 효력은 in 지정어 뒤에 오는 수식에 한정된다. x1.l1′ 은 벡터를 첫 값과 나머지로 구분한 모양이다. x1이 첫 값에 해당하고 l1’이 나머지 값이다. 따라서 x1.l1′ = l1이라는 수식은, l1이라는 벡터의 첫 값을 x1에 대입하고 나머지 값은 l1’에 대입하라는 의미이다.

?는 수식의 동작이 정상적으로 수행되는지를 따지는 연산자이다. ?앞에 오는 수식이 실행 중 문제를 일으키면 ?뒤에 오는 수식이 수행된다. 이는 최근 프로그래밍언어에서 false 혹은 null 을 따지는 것과 유사하지만, ML에서는 failure 혹은 exception을 따진다는 점에서 차이가 있다.

위의 예를 보면 ML 언어의 가장 큰 특징이 잘 나타나 있다.

먼저 함수의 인자에 타입 선언이 전혀 되어 있지 않다. 함수 내에서도 변수에 타입은 선언되어 있지 않다. 이는 리스프와 유사하지만 실제는 그렇지 않다. 리스프 언어는 타입 자체가 없다. 모든 것을 리스트로 보기 때문이다. 하지만 ML은 일종의 추상 타입이다. 타입이 사용되기는 하지만 실행 과정에서 정해지는 방식이다. 실제로 ML은 실행 과정에서 인자의 타입에 따라 함수 결과의 타입을 결정한다. 그래서 ML은 다형성polymorphism을 지원하는 초기 언어이기도 하다.

프로그램 내에 명시적으로 타입을 지정하지 않기 때문에 실행 중에 서로 맞지 않는 타입끼리 연산이 벌어질 가능성이 발생한다. ML은 프로그램 실행 과정 중에 이를 감지해서 예외처리상황exception임을 알린다.

1 2 3 4 5 6