[PL] OCaml Basic

👑 OCaml Basic


💡 주석 (Comment)

OCaml은 여러줄 주석만 지원한다.

(* This is multiline comment *)


💡 Standard I/O

  • 기본 입력

    • read_line() 함수 : 사용자 입력을 문자열로 반환한다.
    • unit 타입, 즉 인자가 없으며, return 타입은 string이다.
    • 한 줄 전체를 string으로 반환하는데, \n (linefeed)는 제외한다.
  • 기본 출력

    • Format 모듈을 사용한 printf
    • Format 모듈은 다양한 형태의 함수를 지원한다.
    • 그 중 printf는 formatted string을 출력해준다.
      let name = "OCaml" in
      let age = 25 in
    
      Format.printf "Name : %s, Age : %d\n" name, age
    


💡 변수 (Variable)

OCaml에서 변수는 특정 값에 묶인(bound) 식별자이다.

변수의 타입은 생략해도 무방하며, OCaml의 타입 시스템이 타입을 추론해준다.

타 언어와 달리 변수 선언과 초기화를 따로 하는 것이 불가능하며, 변수는 선언과 동시에 값에 bound 되어야 한다.

기본적으로 모든 변수는 값의 변경이 불가능하다. 이 때 같은 이름의 변수를 여러 번 선언하는 경우 가장 최근에 선언한 변수에만 접근 가능하며, 이를 variable shadowing이라 한다.

let x = 1 in      (* x는 1이며, 변경 불가능 *)
let x = x + x in  (* 새로운 x 가 이전 x + x에 묶임 *)
x                 (* 이전의 x는 새로운 x에 의해 가려짐(shadowing) *)

1) Global Definitions

  • let [variable] = [expression] 의 형태

  • globally 하게 정의되었기 때문에, 어디서든 사용 가능

2) Local Definitions

  • `let [variable] = [expression] in [expression] 의 형태

  • in은 변수의 scope를 정해준다.

  • 아래의 예시에서 1 + 2 + 3이 계산된 이후 sum에 bound 된다.

    global definition과 다르게 sum은 in 다음의 expression에서 밖에 사용될 수 없다.


✔ Wildcard

OCaml 에서 Wildcard _는 패턴 매칭이나 함수 정의, expression 의 실행 등 다양한 용도로 사용된다. anything 이라는 의미를 가지고 있어, 어떤 값이든 가질 수 있다는 뜻을 가진다.

OCaml에서는 사용하지 않는 값을 변수에 바인딩 하는 것을 금지한다.

즉, 단순히 expression을 실행하려면 wildcard를 사용하는 것이 좋다.

  • expression 실행

image

  • 패턴 매칭
match expression with
| pattern1 -> ~~~
| _ -> ~~~  (* pattern1에 해당되지 않는 모든 값에 대응함 *)


💡 Sequencing

Sequencing은 연속적인 unit expression의 계산을 수행하는 것을 말한다.

  • ; 로 연결된 expression을 순차적으로 실행

  • 마지막 expression을 제외한 모든 expression의 계산 결과는 unit이어야 한다.

  • begin-end expression을 사용하여 명시적으로 표기해주는 것이 일반적이다.

(* Semicolon-only *)
Format.printf "10\n";
Format.printf "20\n";
Format.printf "30\n"

(* begin-end *)
begin
  Format.printf "10\n";
  Format.printf "20\n";
  Format.printf "30\n"
end

(* let-in *)
let _ = Format.printf "10\n" in
let _ = Format.printf "20\n" in
Format.printf "30\n"


💡 Function

OCaml에서 함수는 first-class object 취급을 받는 first-class function이다.

즉, OCaml에서 함수를 다른 함수에 대한 인자로 전달하고, 다른 함수의 값으로 반환하고,

변수에 할당하는 것이 가능하다. (함수 자체가 expression 이자 값임)

  • fun 키워드를 통해 함수를 정의할 수 있다.

  • let definition 또는 let-in definition을 활용하여 이름 있는 함수 정의가 가능하다.

(* 기본형 *)
fun [param_list] -> [expression]

fun x -> x + 1            (* 익명 함수 정의 *)
let f = fun x y -> x + y  (* 익명 함수를 변수 f에 바인딩 *)

let sum x y = x + y       (* 이름 있는 함수 정의 *)
let sum x y = x + y in
Format.printf "Result : %d\n" (sum 3 7)


  • 함수의 타입은 arrow 로 표기 : type -> type

  • 여러 인자를 받는 경우 curried form으로 표기한다.

currying : 여러 인자를 받는 함수를 단일 인자를 받는 함수의 나열로 표현

let add x = x + 1       (* add : int -> int *)

let sum x y = x + y     (* sum : int -> int -> int *)


  • 함수 인자를 tuple 로 받도록 정의할 수도 있다.

  • tuple의 타입은 *를 사용하여 표기한다.

let a = 3, 4                (* p : int * int *)
let b = (3, 'c', "hello")   (* b : int * char * string *)

let sum (x, y) = x + y in
Format.printf "Result : %d\n" (sum(1, 3))


  • 함수가 자기 자신을 호출하기 위해서는(재귀) rec 키워드와 함께 named function 으로 정의해야 한다.
let rec factorial = function
  | 0 -> 1
  | n -> n * factorial (n - 1)  (* rec 키워드를 통해 자기 자신 호출 가능 *)


💡 조건문

OCaml에서의 조건문은 if-then-else expression을 통해 작성된다.

  • if [expression1] then [expression2] else [expression3]

  • expression1 은 반드시 bool 타입이어야 한다.

  • true 이면 expression2, false 이면 expression3 이다.

  • expression2expression3 의 타입은 동일해야 한다.

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

Categories:

Updated:

Leave a comment