ocaml tutorial - seoul national universityropas.snu.ac.kr/~ta/4190.310/11f/ocaml_tutorial11s.pdf ·...
Post on 24-May-2020
7 Views
Preview:
TRANSCRIPT
OCaml Tutorial2011년 봄 프로그래밍 언어 수업
이원찬서울대학교 소프트웨어 무결점 연구센터
들어가기 전에
수업 홈페이지 안내
• 수업 홈페이지
‣ http://ropas.snu.ac.kr/~dreameye/PL
• 조교 홈페이지
‣ http://ropas.snu.ac.kr/~ta/4190.310/11s
두 명의 숙달된 조교들
이원찬 조교
wclee@ropas.snu.ac.kr
138동 215호에 서식
김진영 조교
jykim@ropas.snu.ac.kr
302동 312-2호에 계심
설문조사!
• 나는 OCaml을 사용해본 적이 없다.
• 나는 함수형 언어(OCaml, Scheme, Lisp)를 사용해본 적이 없다.
• 나는 프로그래밍을 할 줄 모른다.
• OCaml을 설치는 해봤다.
OCaml은...
• 불행히도 숙제를 위해 새로 배워야 할 언어
• 하지만 더 나은 프로그래밍을 가능케 해주는 언어
• 함수형, 값 중심, 강한 타입 체계를 사용
다운 받는 곳http://caml.inria.fr/download.en.html
설치 방법
• 설치 파일을 사용
‣ Binary distribution란에서 자신의 운영체제용을 받아 설치
• 소스를 받아서 컴파일
‣ Source distribution을 다운받아 압축 해제 후 컴파일
• 패키지 매니저를 사용
‣ apt-get (Ubuntu), port (Mac)에서 ocaml 패키지를 찾을 수 있음!
컴파일 방법
컴파일 방법
실행기 사용 방법
편집은 뭘로?
• 추천하는 편집기
‣ emacs
‣ vi
• 다음으로 추천하는 편집기
‣ Notepad++
‣ Eclipse + OcaIDE
• 뭐든 문법을 잘 드러내는 기능을 지원하는 것으로!
기본기
값 중심의 언어
• 언어 안에서 돌아다니는 모든 것은 값!
let one = 1
let two = 2
let add = (+)
let three = add one two
값 중심의 언어
• 모든 표현식, 값은 타입이 있음
let one = 1 (* int *)
let two = 2 (* int *)
let add = (+) (* int -> int -> int *)
let three = add one two (* int *)
값 중심의 언어
• 모든 표현식, 값은 타입이 있음
let one : int = 1
let two : int = 2
let add : int -> int -> int = (+)
let three : three = add one two
강한 타입 체계
• 열쇠는 꼭 맞는 열쇠 구멍에 끼워야
let one = 1 (* int *)
let two_point_two = 2.2 (* float *)
let add = (+) (* int -> int -> int *)
let three_point_two = add one two_point_two (* error *)
강한 타입 체계
• 열쇠는 꼭 맞는 열쇠 구멍에 끼워야
let one = 1 (* int *)
let two_point_two = 2.2 (* float *)
let add = (+) (* int -> int -> int *)
let three_point_two = (float_of_int one) +. two_point_two (* float *)
함수형 언어
• 함수도 값!
let one = 1 (* int *)
let add = (+) (* int -> int -> int *)
let add_one = add one (* int -> int *)
let four = add_one 3 (* int *)
let five = add_one (add_one 3)
Hello, World그 끝없는 고찰
Hello, World!
let x = print_string “Hello, World!”
실행 결과는... 아시죠?
Hello, World!
let x = print_string “Hello, World!”
print_string: 문자열을 출력하는 “함수”
Hello, World!
let x = print_string “Hello, World!”
print_string의 타입은 string -> unit
Hello, World!
let x = print_string “Hello, World!”
“Hello, World!”: 문자열(string)
Hello, World!
let x = print_string “Hello, World!”
let x = ...: 등호 오른쪽 표현식의 “값”을 앞으로 x로 부름
Hello, World!
let x = print_string “Hello, World!”
print_string “Hello, World!”의 값은?
Hello, World!
let x = print_string “Hello, World!”
print_string “Hello, World!”의 값은? : 빈(unit) 값
Hello, World!
let x = print_string “Hello, World!”
unit타입: 아무 의미 없는 값의 타입
Hello, World! (ver. 2)
let greeting = “Hello, World!”
let _ = print_string greeting
각 라인은 순서대로 실행
Hello, World! (ver. 2)
let greeting = “Hello, World!”
let _ = print_string greeting
let greeting = ...: 저 문자열을 앞으로 greeting으로 부르겠음
Hello, World! (ver. 2)
let greeting = “Hello, World!”
let _ = print_string greeting
greeting은 “이름”이라 값을 바꿀 수 없음!
Hello, World! (ver. 2)
let greeting = “Hello, World!”
let _ = print_string greeting
greeting은 “이름”이라 값을 바꿀 수 없음!, let이외의 장소에서 =는 값이 같은지검사하는 함수
Hello, World! (ver. 2)
let greeting = “Hello, World!”
let _ = print_string greeting
_ : 무관심의 표현
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
my_print: deco, msg의 두 인자를 받는 함수
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
e1; e2; ... : 표현식 e1, e2, ... 들을 순서대로 실행
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
잠깐... 모든 표현식이 값을 갖는 거 아니었나요?
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
잠깐... 모든 표현식이 값을 갖는 거 아니었나요?: (e1; e2; ...; en)의 값은 en을 실행한 값
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
따라서 my_print의 몸통을 실행하면
‣ 결과 값은 3, 타입은 int
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
print_char: 문자 하나를 화면에 출력하는 함수
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
print_char의 타입은 char -> unit
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
따라서 my_print의 타입은 char -> string -> int
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
‘“‘ : 문자 자료형
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
함수 f를 호출하는 방법: f e1 e2 ...
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
그럼 f(e1, e2, ...)는 뭔가요?
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
그럼 f(e1, e2, ...)는 뭔가요?: 주의! 조금 다른 것을 의미합니다!
“Hello, World!” (ver. 3)let greeting = “Hello, World!”
let my_print deco msg = print_char deco; print_string msg; print_char deco; 3
let x = my_print ‘“‘ greeting
실행 결과는?: 화면에 “Hello, World!” 가 출력됨
“Hello, World!” (ver. 3*)let greeting = “Hello, World!”
let my_print = fun deco -> (fun msg -> print_char deco; print_string msg; print_char deco; 3)
let x = my_print ‘“‘ greeting
fun은 도대체 뭔가요?
“Hello, World!” (ver. 3*)let greeting = “Hello, World!”
let my_print = fun deco -> (fun msg -> print_char deco; print_string msg; print_char deco; 3)
let x = my_print ‘“‘ greeting
fun은 도대체 뭔가요?: “함수값”을 만드는 문법
“Hello, World!” (ver. 3*)let greeting = “Hello, World!”
let my_print = fun deco -> (fun msg -> print_char deco; print_string msg; print_char deco; 3)
let x = my_print ‘“‘ greeting
my_print는...‣ deco를 받아서 함수를 돌려줌‣ 그 함수는 msg를 받아서 출력 후 3을 돌려줌
“Hello, World!” (ver. 3*)let greeting = “Hello, World!”
let my_print = fun deco -> (fun msg -> print_char deco; print_string msg; print_char deco; 3)
let x = my_print ‘“‘ greeting
my_print는...‣ 여전히 타입은 char -> string -> unit‣ 같은 뜻으로 char -> (string -> unit)
“Hello, World!” (ver. 4)let greeting = “Hello, World!”
let my_print deco aux msg = aux deco; print_string msg; aux deco
let _ = my_print ‘“‘ (fun c -> print_char c) greeting
my_print: deco, aux, msg의 세 인자를 받는 함수, 하지만...
“Hello, World!” (ver. 4)let greeting = “Hello, World!”
let my_print deco aux msg = aux deco; print_string msg; aux deco
let _ = my_print ‘“‘ (fun c -> print_char c) greeting
aux: deco를 받아들이는 “함수”
“Hello, World!” (ver. 4)let greeting = “Hello, World!”
let my_print deco aux msg = aux deco; print_string msg; aux deco
let _ = my_print ‘“‘ (fun c -> print_char c) greeting
aux: deco를 받아들이는 “함수”함수를 마음대로 함수에 넘겨줄 수 있다!
“Hello, World!” (ver. 4)let greeting = “Hello, World!”
let my_print deco aux msg = aux deco; print_string msg; aux deco
let _ = my_print ‘“‘ (fun c -> print_char c) greeting
my_print에 넘겨줄 “함수값”을 만듭시다!
“Hello, World!” (ver. 4)let greeting = “Hello, World!”
let my_print deco aux msg = aux deco; print_string msg; aux deco
let _ = my_print ‘“‘ (fun c -> print_char c) greeting
my_print에 넘겨줄 “함수값”을 만듭시다!타입은 char -> unit
“Hello, World!” (ver. 4)let greeting = “Hello, World!”
let my_print deco aux msg = aux deco; print_string msg; aux deco
let _ = my_print ‘“‘ (fun c -> print_char c) greeting
my_print의 타입은 따라서,char -> (char -> unit) -> string -> unit
[Hello, World!) (ver. 5)let greeting = “Hello, World!”
let my_print deco msg = match deco with | (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (‘[‘, ‘)’) greeting
(‘[‘, ‘)’): ‘[‘, ‘)’ 두 문자를 담은 쌍(pair)을 만듬!
[Hello, World!) (ver. 5)let greeting = “Hello, World!”
let my_print deco msg = match deco with | (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (‘[‘, ‘)’) greeting
(‘[‘, ‘)’)의 타입은 char * char
[Hello, World!) (ver. 5)let greeting = “Hello, World!”
let my_print deco msg = match deco with | (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (‘[‘, ‘)’) greeting
쌍에 집어 넣은 값은 어떻게 꺼내나요?
[Hello, World!) (ver. 5)let greeting = “Hello, World!”
let my_print deco msg = match deco with | (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (‘[‘, ‘)’) greeting
쌍에 집어 넣은 값은 어떻게 꺼내나요?: 패턴 매칭(pattern matching)을 사용!
[Hello, World!) (ver. 5)
“만약 deco가 (_ , _) 모양의 값이라면 쪼개서 prolog, epilog로 이름 붙여 주세요!”
let greeting = “Hello, World!”
let my_print deco msg = match deco with | (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (‘[‘, ‘)’) greeting
[Hello, World!) (ver. 5)let greeting = “Hello, World!”
let my_print deco msg = match deco with | (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (‘[‘, ‘)’) greeting
그래서 my_print의 타입은char * char -> string -> unit
[Hello, World!) (ver. 5*)
let greeting = “Hello, World!”
let my_print (prolog, epilog) msg = print_char prolog; print_string msg; print_char epilog
let _ = my_print (‘[‘, ‘)’) greeting
ver. 5를 줄여서 쓴 모양설탕 구조 (syntactic sugar)
[Hello, World!) (ver. 6)type pair = Mk_pair of char * char
let greeting = “Hello, World!”let my_print deco msg = match deco with | Mk_pair (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (Mk_pair (‘[‘, ‘)’)) greeting
type pair = ...: 사용자 정의 타입을 만듬
[Hello, World!) (ver. 6)type pair = Mk_pair of char * char
let greeting = “Hello, World!”let my_print deco msg = match deco with | Mk_pair (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (Mk_pair (‘[‘, ‘)’)) greeting
Mk_pair: pair 타입의 값을 만드는 생성자
[Hello, World!) (ver. 6)type pair = Mk_pair of char * char
let greeting = “Hello, World!”let my_print deco msg = match deco with | Mk_pair (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (Mk_pair (‘[‘, ‘)’)) greeting
Mk_pair: pair 타입의 값을 만드는 생성자,반드시 대문자로 시작해야 함!
[Hello, World!) (ver. 6)type pair = Mk_pair of char * char
let greeting = “Hello, World!”let my_print deco msg = match deco with | Mk_pair (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (Mk_pair (‘[‘, ‘)’)) greeting
pair의 값은 어떻게 쪼개나요?
[Hello, World!) (ver. 6)type pair = Mk_pair of char * char
let greeting = “Hello, World!”let my_print deco msg = match deco with | Mk_pair (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (Mk_pair (‘[‘, ‘)’)) greeting
pair의 값은 어떻게 쪼개나요?: 패턴 매칭은 여전히 여러분의 친구입니다!
[Hello, World!) (ver. 6)type pair = Mk_pair of char * char
let greeting = “Hello, World!”let my_print deco msg = match deco with | Mk_pair (prolog, epilog) -> print_char prolog; print_string msg; print_char epilog
let _ = my_print (Mk_pair (‘[‘, ‘)’)) greeting
my_print의 타입은 pair -> string -> unit
[Hello, World!) (ver. 6*)
type pair = Mk_pair of char * char
let greeting = “Hello, World!”let my_print (Mk_pair (prolog, epilog)) msg = print_char prolog; print_string msg; print_char epilog
let _ = my_print (Mk_pair (‘[‘, ‘)’)) greeting
ver. 6을 줄여서 쓴 모양
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
let greeting = ...: 문자의 리스트를 만들어 greeting이라 이름 붙임
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
greeting의 타입은 char list,string과는 완전 다른 타입!
let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)
a::b: b 리스트 앞에 a가 나타내는 문자를 붙여 “새 리스트”를 만듦
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
a::b: b 리스트 앞에 a가 나타내는 문자를 붙여 “새 리스트”를 만듦, b값은 변하지 않음!
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
[] : 빈 리스트를 의미
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
[‘H’;‘e’;‘l’;‘l’;‘o’]로 줄여서 쓸 수도 있음여전히 설탕 구조 (syntactic sugar)
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
그럼 리스트는 어떻게 쪼개나요?
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
그럼 리스트는 어떻게 쪼개나요?: 저희 보람상조... 아니, 패턴매칭이 도와드립니다.
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
두개의 패턴: 만드는 방법이 두 가지 이므로
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
“빈 리스트라면”: 손 털고 집에 갑니다
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
“문자가 한 개 들어있다면”: 해당 문자를 출력하고 나머지 리스트에 대해 반복
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
rec은 못보던 앤데요?
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
rec은 못보던 앤데요?: my_print를 정의하는데 my_print를 사용
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
rec은 못보던 앤데요?: my_print를 정의하는데 my_print를 사용, 재귀함수(recursive function)임을 표시!
반복을 표현하는 두 방법
int a[3] = {1, 2, 3};
for(i = 0; i < 3; ++i) foo(a[i]);
let a = [1; 2; 3]
let rec for x = match x with | [] -> () | b :: x’ -> foo(b); for(x’)
let run = for a
• 절차적 방법(imperative)
• 재귀적 방법(recursive)
반복을 표현하는 두 방법• 절차적 방법
(imperative)• 재귀적 방법
(recursive)
문제 문제
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 7)let greeting = ‘H’::‘e’::‘l’::‘l’::‘o’::[]let rec my_print msg = match msg with | [] -> () | c :: msg’ -> print_char c; my_print msg’
let _ = my_print greeting
my_print의 타입은 char list -> unit
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 8)type my_list = Nil | Cons of char * my_list
let greeting = Cons (‘H’, Cons (‘e’, ... , Nil) ... )let rec my_print msg = match msg with | Nil -> () | Cons (c, msg’) -> print_char c; my_print msg’
let _ = my_print greeting
type my_list = ...: 사용자 정의 귀납(inductive) 타입을 만듦
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 8)type my_list = Nil | Cons of char * my_list
let greeting = Cons (‘H’, Cons (‘e’, ... , Nil) ... )let rec my_print msg = match msg with | Nil -> () | Cons (c, msg’) -> print_char c; my_print msg’
let _ = my_print greeting
값을 만드는 규칙을 또는(|) 기호로 구분해서 적기,생성자 이름은 반드시 대문자로 시작해야함!
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 8)type my_list = Nil | Cons of char * my_list
let greeting = Cons (‘H’, Cons (‘e’, ... , Nil) ... )let rec my_print msg = match msg with | Nil -> () | Cons (c, msg’) -> print_char c; my_print msg’
let _ = my_print greeting
let greeting = ...: my_list 타입의 값을 만들어서 greeting이라고 부릅시다!
‘H’::‘e’::‘l’::‘l’::‘o’ (ver. 8)type my_list = Nil | Cons of char * my_list
let greeting = Cons (‘H’, Cons (‘e’, ... , Nil) ... )let rec my_print msg = match msg with | Nil -> () | Cons (c, msg’) -> print_char c; my_print msg’
let _ = my_print greeting
값을 쪼갤때는 여전히 패턴 매칭을 사용합니다!
잠깐, 리스트랑 쌍이 뭐가 다른건가요?
(1, 2)(1, (2, 3))(1, (2, (3, 4)))
[1; 2][1; 2; 3][1; 2; 3; 4]
라고 쓴 것,뭐가 다른거죠?
라고 쓴 것과
귀납법의 아름다움(1, 2) (* int*int *)(1, (2, 3)) (* int*(int*int) *)(1, (2, (3, 4))) (* int*(int*(int*int) *)
[1; 2] (* int list *)[1; 2; 3] (* int list *)[1; 2; 3; 4] (* int list *)
이 셋은 모두 같은 타입입니다.
이 셋은 모두 타입이 다릅니다.
귀납법의 아름다움(1, 2) (* int*int *)(1, (2, 3)) (* int*(int*int) *)(1, (2, (3, 4))) (* int*(int*(int*int) *)
[1; 2] (* int list *)[1; 2; 3] (* int list *)[1; 2; 3; 4] (* int list *)
이 셋은 모두 같은 타입입니다.
이 셋은 모두 타입이 다릅니다.
리스트는 길이와 상관없이 같은 타입으로 다룰 수 있습니다!
다 같이 풀어 봅시다
• 숙달된 조교의 시범: length, map
• 여러분이 해 볼것: mem
‣ if문이 필요할 것입니다- if e1 then e2 else e3: e1값이 true면 e2, false면 e3 의 값을 돌려줌 - = : 같은 타입 두 값을 비교해서 true / false를 돌려줌 - then과 else를 항상 써줘야 합니다- then과 else에 오는 표현식은 타입이 같아야 합니다
못다한 이야기
[Hello, World!) (ver. 6**)type pair = { prolog : char; epilog : char }
let greeting = “Hello, World!”let my_print deco msg = print_char deco.prolog; print_string msg; print_char deco.epilog
let _ = my_print { prolog = ‘[‘; epilog = ‘)’} greeting
type pair = ...: 사용자 정의 레코드 타입을 만듬
[Hello, World!) (ver. 6**)type pair = { prolog : char; epilog : char }
let greeting = “Hello, World!”let my_print deco msg = print_char deco.prolog; print_string msg; print_char deco.epilog
let _ = my_print { prolog = ‘[‘; epilog = ‘)’} greeting
record.field: 레코드에서 해당 필드 값을 가져옴
[Hello, World!) (ver. 6**)type pair = { prolog : char; epilog : char }
let greeting = “Hello, World!”let my_print deco msg = print_char deco.prolog; print_string msg; print_char deco.epilog
let _ = my_print { prolog = ‘[‘; epilog = ‘)’} greeting
record.field: 레코드에서 해당 필드 값을 가져옴, 혹은 패턴 매칭으로 쪼갤수도 (각자 찾아보기!)
[Hello, World!) (ver. 6**)type pair = { prolog : char; epilog : char }
let greeting = “Hello, World!”let my_print deco msg = print_char deco.prolog; print_string msg; print_char deco.epilog
let _ = my_print { prolog = ‘[‘; epilog = ‘)’} greeting
{ field = v; ... }: 레코드 타입의 값을 주어진 초기 값을 사용해서 만듦
다형 타입(polymorphic type)
• “리스트는 원소의 내용을 몰라도 만들 수 있다”
1 :: 2 :: []
‘a’ :: ‘b’ :: []
“Hello” :: “World” :: []
다형 타입(polymorphic type)
• “리스트는 원소의 내용을 몰라도 만들 수 있다”
:: :: []
1 :: 2 :: []
‘a’ :: ‘b’ :: []
“Hello” :: “World” :: []
다형 타입(polymorphic type)
• “리스트는 원소의 내용을 몰라도 만들 수 있다”
:: :: []
1 :: 2 :: []
‘a’ :: ‘b’ :: []
“Hello” :: “World” :: []
(* int list *)
(* char list *)
(* string list *)
(* ‘a list *)
다형 타입(polymorphic type)
• 예제type ‘a my_list = | Nil | Cons of ‘a * ‘a my_list
let int_my_list = Cons (1, Cons (2, Nil)) (* int my_list *)
let char_my_list = Cons (‘a’, Cons (‘b’, Nil)) (* char my_list *)
모듈 (module)
• 서로 관련이 있는 코드들의 묶음
module List = (* 이름은 반드시 대문자로 시작 *)struct type ‘a t = Nil | Cons of ‘a * ‘a t
let length : ‘a t -> int = fun l -> ... end
let l = List.Cons (1, List.Nil) (* int List.t *)let length = List.length l (* int *)
모듈 (module)
• 각 파일은 하나의 모듈
type ‘a t = Nil | Cons of ‘a * ‘a t
let length : ‘a t -> int = fun l -> ...
list.ml
모듈 (module)
• 각 파일은 하나의 모듈
type ‘a t = Nil | Cons of ‘a * ‘a t
let length : ‘a t -> int = fun l -> ...
module List = struct
end
모듈 (module)
• 각 파일은 하나의 모듈
type ‘a t = Nil | Cons of ‘a * ‘a t
let length : ‘a t -> int = fun l -> ...
list.ml
let l = List.Cons (1, List.Nil) let length = List.length l
user.ml
모듈 (module)
• 매번 모듈 이름 붙이기 귀찮다면
type ‘a t = Nil | Cons of ‘a * ‘a t
let length : ‘a t -> int = fun l -> ...
list.ml
open Listlet l = Cons (1, Nil)let length = length l
user.ml
아름답지 못한, 허나가끔 유용한
• 참조 타입 (reference)
let a = ref 1 (* int ref *)
let b = !a (* b = 1, int *)
let _ = a := 2 (* unit *)
let c = !a (* c = 2, int *)
아름답지 못한, 허나가끔 유용한
• 배열 (array)
let a = [| 1; 2; 3 |] (* int array *)
let first = a.(0) (* first = 1, int *)
let _ = a.(0) <- 4 (* unit *)
let fisrt‘ = a.(0) (* first‘ = 4, int *)
아름답지 못한, 허나가끔 유용한
• 예외 (exception)
exception Empty_list (* 예외 이름 *) (* 반드시 대문자로 시작 *)
let head l = match l with | [] -> raise Empty_list | a :: l’ -> a
let x = try head [] with Empty_list -> 0 (* x = 0, 예외 처리 *)
좀 더 자세한 이야기는...
• OCaml 사용자 매뉴얼
‣ http://caml.inria.fr/pub/docs/manual-ocaml
• 라이브러리 사용법
‣ http://caml.inria.fr/pub/docs/manual-ocaml/libref/index_modules.html
‣ Pervasives, List, String 등을 참조
• 우리의 영원한 친구 구글
끝내며...
• 컴파일 안되는 소스는 절대, Never 채점안합니다.
• 제출 전 최대한 많이 테스트 해봅시다.
• 강조하지만 남의 것을 탐하면 안됩니다.
‣ 우리 연구실은 유사한 코드 찾아내는 기술도 연구하는 곳입니다.
• 조교는 항상 여러분 곁에 있습니다.
‣ 게시판, 메일, 방문의 방법을 적극 활용 바랍니다.
top related