KoreanFoodie's Study
OCaml 기초 - OCaml 타입, 함수 본문
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 ( ) -> ...
으로 정의가 되어 있다.
i
는 read_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에 중요한 개념들을 좀 더 알아보자.
'Tutorials > Ocaml' 카테고리의 다른 글
OCaml Library module "List" implementation (0) | 2019.09.17 |
---|---|
OCaml 예제 코드 (Quicksort, Stack, Calculator, Prime Number Generator) (0) | 2019.09.17 |
OCaml 기초 2 - 자료형, Currying, match-with, polymopic type, reference (0) | 2019.09.17 |