Ocaml 은 모듈 시스템을 지원한다.
모듈은 클래스와 비슷하다. 객체화 시킬 수 없는 클래스라고 생각하면 된다.
한마디로 재료들의 집합니다.
각각의 모듈은 자료(변수)와 함소(행동)로 구성되어 있다.
클래스와 유사하지만 상태를 갖지 않는다.
모듈은 그 자체로 타입이 아니며, 객체화는 불가능하고, 모듈의 함수를 호출하거나 자료를 읽는 행위만 가능하다.
모든 소스코드 파일은 그 자체로 모듈이 된다. (파일 이름이 곧 모듈)
지난 시간에 hw1.ml 에 있는 calc 함수를 테스트할 때 Hw1.calc 를 통해 호출한 기억이 있다. 이때 Hw1 을 모듈이라고 한다.
Nested Module 이란 모듈 내에 정의된 모듈을 말한다.
이것은 다른 언어에서 클래스 안에 클래스가 있는 inner class 와 유사한 개념이다.
파일 내에 module [module_name] = struct [defs] enddefinition을통해 생성할 수 있다.
Nested 모듈에 접근할 떄는 [module_name].[nested_module_name].[var_name] 로 접근한다.
open 키워드를 사용하면 모듈의 변수를 접근할 때 모듈 이름을 생략할 수 있다. C++ 에서 using namespace std 를 하면 std::cin 에서 std 를 생략할 수 있는 것과 동일하다.
다만 A 모듈에도 add 가 있고 B 모듈에도 add 가 있을 떄 둘 다 open 하면 충돌이 발생할 수도 있다.
따라서, let-in expression 을 통해 특정 스코프 내에서만 모듈을 개방할 수도 있다.
let open [module_name] in [expression]
만약 모듈 이름이 긴 경우, “약자”를 이용하여 모듈을 지칭할 수 있다.
module [abbreviation] = [module_name]
패턴 매칭이란 값의 “형태”에 따라 다른 행동을 수행하는 것이다.
match-with expression 을 통해 수행할 수 있다.
우선 match-with expression 은 그 자체로 expression 이므로 값으로 계산한다.
if-else 와 유사한데, 값의 “형태”에 따라 다르게 처리해야할 때 유용하다.
다만 처리하지 않은 “형태”가 있다면 컴파일러에서 warning 을 발생시킨다.
pattern 과 매칭되는지 1부터 확인하고 매칭되면 해당 expression 을 계산한다. 매칭 실패면 다음으로 넘어간다.
match expression with
| pattern1 -> expression1
| pattern2 -> expression2
...
| patternN -> expressionN
이때 패턴은 상수인지 변수인지에 따라 다르게 동작하는데
패턴이 상수라면 계산 값이 패턴과 일치하는지를 매칭하고, 변수일 경우는 항상 매칭에 성공한다. (binding occurrence)
wildcard 패턴은 임의의 expression 을 활용하여 항상 매칭에 성공시키는 것인데 이를 빼면 컴파일 warning 이 발생한다. Dune 빌드 시스템은 warning 을 error 로 판별하므로, 무조건 껴줘야하는 경우가 많다.
왜 이런일이 발생하냐면 Ocaml 컴파일러는 expression 의 타입을 기반으로 패턴 매칭의 완전성을 검사한다.
즉, expression 이 int 라면 모든 int 값을 커버해야한다.
따라서 이때 failwith를 활용할 수 있는데, 이는, Failure 예외를 발생시키는 OCaml 내장함수이다.
패턴 매칭 시 주의할 것은 각 매치 케이스의 expression 은 모두 동일한 타입을 가져야한다.