KoreanFoodie's Study

OCaml 기초 - OCaml 타입, 함수 본문

Tutorials/Ocaml

OCaml 기초 - OCaml 타입, 함수

GoldGiver 2019. 9. 16. 20:33

OCaml 언어 :

Ocaml은 여러가지 사용법을 가지는 상위 (high-level)언어이다.

절차형(imperative), 객체지향(object oriented), 함수형(functional) 등의 프로그래밍을 모두 지원한다.

Java처럼, 자동으로 메모리를 관리해 주는 Garbage collector가 존재한다.

타입 시스템이 내장되어 매우 안정적으로 사용할 수 있다.

절차형 VS 값 중심형

절차형 언어는 기게에게 순서대로 명령을 전달한다. 함수형 언어의 경우, 값 중심으로 기계에게 식의 계산을 시키는 식으로 동작한다.


OCaml 기초 - 값 정의

  • 정수 값
let i = 1
  • 문자열 값
let s = "hello world"
  • Boolean 값
let b = true
  • unit
let _ = print_endline "hello world"

이때, 값의 이름은 소문자로 시작해야 한다!


타입

모든 값은 타입을 가진다. (* 해당 기호는 주석을 의미한다. *)

OCaml은, 타입 추론 시스템이 있어 자동으로 정확하게 타입을 추론해 주고, 프로그램에 타입 에러가 있다면 미리 잡아준다.

따라서, 일반적으로는 코딩 시 타입을 쓰지 않아도 좋다. 하지만 모듈 타입이나 레퍼런스(C에서의 포인터 개념)등에서는 반드시 써야만 하는 경우도 존재한다.

다만 가독성을 위해, 프로그램이 커지면 타입을 명시하는 것이 좋다.

let i = 1 (* i:int *) 
let s = "hello world" (* s:string *)
let b = true (* b:bool *)

타입을 명시해서 코딩을 해 줄 수도 있다.

let i:int  = 1 (* i:int *) 
let s:string = "hello world" (* s:string *)
let b:bool = true (* b:bool *)

함수

이 부분부터 함수형 언어의 차이가 두드러지기 시작한다.

함수를 정의하고 사용해 보자.

let incr x = x + 1
let y = incr 5

이때, incr라는 함수는 argument로 들어간 x에 1값을 더해주는 함수이다. (이 함수의 타입은 int->int인데, 이는 추후에 설명한다)

다른 방식으로 함수를 정의할 수도 있다.

let incr = fun x -> x+1
let y = incr 5

이때, fun x-> x+1 은 Anonymous function으로, int를 받아 int를 리턴하는 함수이다. Anonymous function은 임시적으로 특정 역할을 수행하는 함수를 정의할 때 유용하게 사용될 수 있다. ->가 생소하게 느껴질 수 있는데, 이는 return 대신 화살표를 이용한다고 생각하면 직관적으로 알아보기 쉬울 것이다.

incr 와 fun을 합쳐서 아래와 같이 쓸 수도 있다.

let y = (fun x -> x+1) 5

중요한 점

OCaml은 함수도 값으로 취급한다.

즉, 위처럼 let incr x = x + 1을 정의했을 때, incr라는 값(함수)에 incr라는 이름을 붙인 것이다.

모든 값은 타입을 가지므로, 함수도 타입을 가진다.

let incr : int -> int = fun x -> x + 1
let incr’ : float -> float = fun x -> x +. 1.0 

let in 문법

let ... = ... in ... 문법은 먼저 값을 정의하고 나중에 그 값을 활용할 때 매우 유용한 문법이다.

let echo : unit -> unit = fun ( ) ->
    let i = read_int ( ) in
    let str = string_of_int i in
    print_endline ("Your input : " ^ str)
    (* ^ : string concat operator *)

위 코드를 보자. echo function은 unit type을 받아 unit type을 리턴하는 함수이다. unit은 임의의 타입을 받는다고 정의할 때 활용되는 타입이므로, 여기서는 크게 신경쓰지 않아도 된다.

echo 함수는 '함수'인데, =다음을 보면 fun ( ) -> ...으로 정의가 되어 있다.

iread_int ( ) in인데, 이는 사용자 인풋을 읽는다는 뜻이다. 이때, i는 아래의 string_of_int i에서 활용되며, type이 string으로 변환된다.

그리고 let str ... = ... in으로 정의된 str은 그 다음 줄에서 print_endline의 변수로 활용된다.

^ 기호는 스트링을 합치는 operator로 활용된다.

OCaml의 main 함수?

Ocaml 코드는 main이 없다.

일련의 정의(let)의 집합으로 구성되며, 위에서부터 하나씩 실행된다.

facrotiral 함수의 예시를 보자.

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

let x = fact 10
let _ = print_endline (string_of_int x)

먼저, 함수를 정의할 때 rec를 이름 앞에 붙여주었는데, 이는 해당 함수가 재귀적으로 호출됨을 의미한다. 재귀함수의 경우 rec을 붙여주어야 한다.

만약 n이 0보다 작거나 같으면, 1을 return하는데, OCaml은 return을 쓰지 않고 then으로 처리한다.
아래 let _은 print_endline 이라는 함수를 호출함에 있어서, 값을 정의해주어야 하는데, 추후에 쓸 일이 없는 의미없는 함수이므로 _를 붙여 쓰고 버린다고 이해하면 된다.

다음 글에서 OCaml에 중요한 개념들을 좀 더 알아보자.

Comments