Caml

Caml
패러다임다중 패러다임: 함수형, 명령형
계열ML
설계자제라르 위에, 기 쿠지노, 아스칸데르 수아레스, 피에르 웨이스, 미셸 모니 (헤비 Caml), 그자비에 르루아 (Caml Light)
개발자INRIA, ENS
발표일1985년(41년 전)(1985)
최근 버전0.75
최근 버전 출시일2002년 1월 26일(24년 전)(2002-01-26)
자료형 체계추론, 정적, 강함
운영 체제크로스 플랫폼: 유닉스, 리눅스, macOS; 윈도우
라이선스QPL 1, LGPL 2 (Caml Light)
웹사이트caml.inria.fr
영향을 받은 언어
ML
영향을 준 언어
OCaml

Caml(본래 범주형 추상 기계 언어를 뜻하는 Categorical abstract machine의 약자)은 ML 프로그래밍 언어 계열의 방언인 다중 패러다임, 범용, 고급, 함수형 프로그래밍 언어이다. Caml은 프랑스의 프랑스 컴퓨터 과학 및 자동화 연구소(INRIA)와 고등사범학교(ENS)에서 개발되었다.

Caml은 정적으로 자료형이 결정되며, 엄격하게 평가되고, 자동 메모리 관리를 사용한다. Caml의 주요 후손인 OCaml은 언어에 객체 지향 프로그래밍 (객체) 계층을 포함한 많은 기능을 추가했다.

예제

다음에서 #은 Caml 프롬프트를 나타낸다.

Hello World

"Hello, World!" 프로그램은 다음과 같다.

print_endline "Hello, world!";;

계승 함수 (재귀 및 순수 함수형 프로그래밍)

계승(팩토리얼)과 같은 많은 수학 함수는 순수 함수형 형태로 가장 자연스럽게 표현된다. 다음의 재귀적, 순수 함수형 Caml 함수는 계승을 구현한다.

let rec fact n = if n=0 then 1 else n * fact(n - 1);;

이 함수는 패턴 매칭을 사용하여 동일하게 작성할 수 있다.

let rec fact = function
  | 0 -> 1
  | n -> n * fact(n - 1);;

이 후자의 형식은 재귀 관계로서 계승의 수학적 정의이다.

컴파일러는 이 함수의 자료형을 int -> int로 추론했는데, 이는 이 함수가 정수를 정수로 매핑함을 의미한다. 예를 들어 12!은 다음과 같다.

 # fact 12;;
 - : int = 479001600

수치 미분 (고차 함수)

Caml은 함수형 프로그래밍 언어이므로, Caml 프로그램에서 함수를 생성하고 전달하기가 쉽다. 이 능력은 매우 많은 응용 분야를 가진다. 함수의 수치 미분을 계산하는 것이 그 예이다. 다음의 Caml 함수 d는 주어진 함수 f를 주어진 점 x에서 수치 미분한다.

let d delta f x =
  (f (x +. delta) -. f (x -. delta)) /. (2. *. delta);;

이 함수는 작은 값 delta를 필요로 한다. 델타에 대한 좋은 선택은 계산기 엡실론의 세제곱근이다.

함수 d의 자료형은 float을 (float -> float) -> float -> float 자료형을 가진 또 다른 함수로 매핑함을 나타낸다. 이를 통해 인수를 부분적으로 적용할 수 있다. 이러한 함수형 스타일을 커링이라고 한다. 이 경우, 첫 번째 인수 delta를 d에 부분 적용하여 더 전문화된 함수를 얻는 것이 유용하다.

# let d = d (sqrt epsilon_float);;
val d : (float -> float) -> float -> float = <fun>

추론된 자료형은 대체된 d가 첫 번째 인수로 float -> float 자료형의 함수를 기대하고 있음을 나타낸다. x3−x−1의 x=3에서의 미분에 대한 수치 근사값은 다음과 같이 계산할 수 있다.

# d (fun x -> x *. x *. x -. x -. 1.) 3.;;
- : float = 26.

정답은 f′(x)=3x2−1→f′(3)=27−1=26이다.

함수 d는 또 다른 함수(f)를 인수로 받기 때문에 "고차 함수"라고 불린다. 더 나아가 x 인수를 생략하면서 d를 적용함으로써 f의 (근사) 도함수를 생성할 수 있다.

# let f' = d (fun x -> x *. x *. x -. x -. 1.) ;;
val f' : float -> float = <fun>

커링된 함수와 고차 함수의 개념은 수학적 프로그램에서 명확하게 유용하다. 이러한 개념은 대부분의 다른 형태의 프로그래밍에도 동일하게 적용될 수 있으며 코드를 훨씬 더 공격적으로 분해하는 데 사용될 수 있어, 결과적으로 더 짧은 프로그램과 더 적은 버그를 만들어낸다.

이산 웨이블릿 변환 (패턴 매칭)

2의 거듭제곱 길이인 숫자 리스트에 대한 1차원 하르 웨이블릿 변환은 Caml에서 매우 간결하게 구현될 수 있으며, 리스트에 대한 패턴 매칭을 사용하는 훌륭한 예이다. 리스트 앞부분에서 요소 쌍(h1 및 h2)을 가져와 그 합과 차를 각각 리스트 s와 d에 저장한다.

# let haar l =
   let rec aux l s d =
     match l, s, d with
       [s], [], d -> s :: d
     | [], s, d -> aux s [] d
     | h1 :: h2 :: t, s, d -> aux t (h1 + h2 :: s) (h1 - h2 :: d)
     | _ -> invalid_arg "haar"
     in aux l [] [];;
val haar : int list -> int list = <fun>

예를 들면 다음과 같다.

  # haar [1; 2; 3; 4; -4; -3; -2; -1];;
   - : int list = [0; 20; 4; 4; -1; -1; -1; -1]

패턴 매칭을 사용하면 복잡한 변환을 명확하고 간결하게 나타낼 수 있다. 또한, Caml 컴파일러는 패턴 매칭을 매우 효율적인 코드로 변환하며, 때로는 case 문으로 작성된 동등한 코드보다 더 짧고 빠른 프로그램을 만들어낸다(Cardelli 1984, p. 210.).

역사

첫 번째 Caml 구현은 1987년 프랑스 컴퓨터 과학 및 자동화 연구소(INRIA)에서 아스칸데르 수아레스에 의해 리스프로 작성되었다.

그 후속작인 Caml Light는 그자비에 르루아와 다미앵 돌리제에 의해 C로 구현되었으며, 원본은 더 높은 메모리 및 CPU 요구 사항 때문에 "헤비(Heavy) Caml"이라는 별명이 붙었다.

Caml Special Light는 핵심 언어에 강력한 모듈 시스템을 추가한 완전한 재작성 버전이었다. 이후 객체 지향 프로그래밍 (객체) 계층이 추가되어 Objective Caml이 되었고, 결국 OCaml로 이름이 변경되었다.

같이 보기

각주

  1. ↑ “Latest Caml Light release”. 2020년 2월 22일에 확인함.
  2. 1 2 3 "A History of Caml", inria.fr

참고 문헌

외부 링크