Ocaml Basic
여러줄의 주석만 지원된다.
(* write your comment here *)
let [variable] = [expression]
✔ expression의 값이 계산된 후, variable에 bound 된다.
let x = 3 + 4;;
✔ 변수가 "값 7로 바운드 되었다(variable x is bound to value 7)"고 한다.이 값은 바뀔 수 없음!
-> 자료형을 명시하지 않았지만 ocaml은 w,x는 int형으로 y,z는 string형으로 type inference를 한다.
let [variable] = [expression1] in [expression2]
✔ let : 변수 선언
✔ in : 변수의 범위(scope)
let x = e1 in e2
✔ e1의 값이 계산된 후 x에 bound된다. 단, x가 사용될 수 있는 scope는 e2이다.
✔ e2의 값은 전체 expression의 값이 된다.
첫 번째 '전체' exrpression의 값은 3, 두번째는 6, 세번째는 4가 된다.
🔔 Ocaml에서 변수는 값 변경이 불가능하다. (Variables are immutable)
- 한번 변수에 값이 bound된다면 변경할 수 없다.
- 두 개의 변수가 같은 이름을 가진다면 variable shadowing이 일어난다.
let x = 1 in // a
let x = x + x // b
// a와 b의 x는 다른 변수이며, 각각 다른 변수가 선언된 것이다. -> variable shadowing.
in x // 가장 최근에 적용한 x를 reference하게 된다. (b의 x) -> 2 return
let a = 1 in a;;
let a = 1 in a * 2;;
let a = 1 in let b = a + a in let c = b + b in c + c;;
Let d = let a = 1 in let b = a + a in let c = b + b in c + c;;
nothing, non, void 등 아무값도 아닌 것을 'Unit Expression'이라고 한다.
(evaluate consecutive unit expressions)
Semicolon-only 방식을 사용할 수도 있지만, begin-end 방식(앞뒤에 괄호를 붙이는 것과 유사한 개념)을 사용하는 것이 더 일반적이다!
value가 first class인 것은 아래 3가지 조건을 만족하는 것이다.
(1) variable에 저장되어야한다.
(2) function의 파라미터로 전달될 수 있어야 한다.
(3) function의 리턴값으로도 사용할 수 있어야 한다.
-> C언어 등 대부분의 언어에서 함수를 매개변수로 주거나, 리턴할 수는 없다. 그러나 함수형 언어에서는 함수를 인자로 넘겨주거나 리턴할 수 있다.
๏ param_list : 파라미터 리스트
๏ Expression : 함수 Body의 내용
๏ id : 함수 이름
๏ param_list : 파라미터 리스트
๏ Expression : 함수 Body의 내용
๏ expression2 : 함수를 실행하는 expression
함수 타입은 화살표로 표시된다.
๏ type1 : 파라미터 타입
๏ type2 : 함수 Body의 타입
๏ f: int x int x int -> int => f: int -> int -> int -> int
let inc x = x+1 // int type을 받아서 int 리턴
// inc : int -> int
let sum x y = x+y // sum: int -> int -> int
let sum x y = x + y in
let sum' = sum 1 in // sum' : int -> int
// sum은 인수 2개인데 한개만 받음 -> partial evaluation이다. 한 개 먼저 일부 실행하여 sum'에 저장한다.
let res = sum 3 in // res : int
// 두번째 인자 넘겨줌
Format.printf "Result: %d\n" res
함수를 인자로 받거나 리턴하는 함수
app 은 f x를 인자로 받는데, f가 함수이기 때문에 함수를 인자로 받는 high order function 이다.
sum은 x를 인자로 받아서, 함수를 리턴하는 함수이다. 리턴하는 함수는 int를 받아서 int를 리턴하는 함수이다.
named function으로 rec 키워드를 이용하면 재귀함수를 정의할 수 있다.
rec 키워드가 없다면 에러가 발생한다.
순서가 있는 값들의 컬렉션
각 값은 타입이 다를 수 있다.
파이썬의 튜플과 동일하다.
튜플의 타입은 별표시로 표시된다. ➡ type type
ex. (1, “hi”) : int string
Let or let-in을 이용해서 튜플 요소를 각 변수에 바인딩시킬 수 있다.
➡ let x, y = (1,3) or let x,y = (1,3) in x + y ➡ x가 1에 binding 되고 y가 3에 바인딩된다.
만약 be가 참이면, e1의 결과값이 전체 리턴값이 되고 아니면 e2의 결과값이 전체 리턴값이 된다.
e1과 e2의 타입은 동일해야 한다.
조건문의 조건식은 boolean 값만 올 수 있다.
๏ if 2 > 1 then 0 else 1;;
➡ : int = 0
๏ If 2 < 1 then 0 else 1;;
➡ : int = 1
public static int f(int n)
{
int a = 2;
return a * n;
}
let f n =
let a = 2 in
a * n;;
// type 추론 = val f : int -> int = <fun>
f 함수는 int를 받아서 int를 반환하는 함수라는 것을 추론한다.
let sum_if_true test first second = (if test first then first else 0) + (if test second then second else 0);; val sum_if_true : (int -> bool) -> int -> int -> int = <fun>
1) first와 second의 type은 int여야 한다. 왜냐하면 조건문의 branch는 같은 타입이어야 하기 때문이다.
2) test의 type은 함수일 것이다. test가 함수를 call 하는 것처럼 사용되었기 때문에 a->b 함수 타입이다.
3) test함수의 리턴값 (b)는 불리언 타입일 것이다. 조건문의 조건식으로 사용되었기 때문이다.
4) test함수의 인자값 (a)는 int일 것이다.
5)val sum_if_true : (int -> bool) -> int -> int -> int = <fun>
let sum_if_true (test : int -> bool) (x : int) (y : int) : int =
(if test x then x else 0) + (if test y then y else 0);;
val sum_if_true : (int -> bool) -> int -> int -> int = <fun>
let sum_if_true (test : int -> int) (x : int) (y : int) : int =
(if test x then x else 0) + (if test y then y else 0);;
// Error: The expression (test x) has type int but an expressionwas expected of type bool;