목차
📁 모듈 시스템(Module system)
📌 모듈은 자료(변수)와 행동(함수)로 구성되는데, 함수형 언어에서 행동은 곧 자료이므로 모듈은 자료의 모음이다.
OCaml은 모듈 시스템을 지원하며, 프로그램은 여러개의 모듈로 구성된다.
JAVA/C++의 클래스와 유사하다.
🔎 모듈과 클래스의 차이점
모듈은 그 자체로 타입이 아니다. 때문에 객체화할 수 없으며, 상태(state)를 지니지 않는다.
클래스는 instance를 가질 수 있으며 각 객체마다 상태를 지니지만,
모듈은 단순히 자료들의 모음일뿐이므로 함수를 호출하거나 자료를 읽는 행위만 가능하다.
이때 state란, class를 instance화 했을때 볼 수 있다.
예를 들어 아래와 같은 class A가 존재하고, x, y라는 instance가 존재한다고 가정하자.
class A { int v; }
A x; A y;
이 때 x라는 객체 안에 v가 있고, y라는 객체 안에 v가 존재한다. 두 v는 각 객체마다 달라질 수 있으며, 이를 상태라고 한다.
OCaml의 모듈은 위와 같이 어떤 상태가 객체에 귀속되지 않으므로 static과 유사하다고 볼 수 있다.
📁 OCaml에서의 module system 예시
모든 소스코드 파일은 그 자체로 모듈이 된다.
모듈이름은 파일 이름을 그대로 따오되, 맨 앞글자를 대문자로 바꾸어 사용한다.
모듈 이름의 맨 앞글자가 대문자가 아닌 경우 compiler error가 발생한다.
예를 들어 operation.ml이라는 파일이 있을 때, 이를 모듈로 사용하기 위해서 Operation과 같이 바꿀 수 있다.
모듈 이름을 이용하여 모듈 내의 변수 또는 함수에 접근할 수 있다.
[moduel_name].[var_name]
📝 사용 예시
operation.ml에 definition이 나열되어있어 오류가 날 것 같아 보일 수 있지만, 파일 내에서 사용하지 않는 definition은 컴파일시 오류가 나지 않는다.
📁 Nested Module
Nested Module이란, 모듈 내에 정의된 모듈을 뜻한다.
module [module_name] = struct [defs] end
* defs : definition들의 나열
위 코드는 definition이다.
파일이 곧 모듈이므로, 위 definition으로 생성된 모듈은 모두 파일이라는 모듈 내에서 생긴 모듈이기 때문에 nested module이다.
C++ / Java의 inner class와 유사한 기능이다.
Nested module에 접근하는 방법은 다음과 같다.
[module_name].[nested_module_name].[var_name]
📝 사용 예시
모듈 안의 모듈 안의 모듈을 만드는 것도 가능하다.
📁 Module opening
모듈을 개방(open)하여 모듈의 변수를 접근할 때 모듈 이름을 생략할 수 있다.
open [module_name]
위와 같은 방법으로 현 scope에서 모듈 내 변수를 모듈 이름 없이 접근할 수 있다.
모듈 내의 definition들을 해당 위치에 붙여넣기 한 효과를 낸다.
위 코드도 definition이다.
open 코드 아래부터 해당되는 모듈이름을 생략할 수 있다.
C++의 using namespace와 유사하다.
🔎 주의사항
여러 모듈에 같은 이름이 있다면 confilct가 발생할 수 있다.
open FloatOp 코드가 open IntOp보다 아래에 있어서 add가 shadowing된다.
FloatOp.add의 인자로 int가 전달되는 것으로 판단되기 때문에 컴파일 오류가 발생한다.
🔎 local module opening
let-in expression을 사용하여 특정 scope 내에서만 모듈을 개방할 수 있다.
let open [module_name] in [expression]
📝 사용 예시
📁 Module renaming
모듈 이름이 긴 경우, "약자"를 이용하여 모듈을 저장할 수 있다.
module [abbrevation] = [module_name]
* abbreviation : 모듈의 이름을 지칭할 약자
abbreviation에 와일드카드를 쓸 수는 없다.
📝 사용 예시