User Tools

Site Tools


lecture:4clojure:level-elementary-easy

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

lecture:4clojure:level-elementary-easy [2015/12/03 10:38]
psk810 [let 문구]
lecture:4clojure:level-elementary-easy [2019/02/04 14:26]
Line 1: Line 1:
-====== Elementary/​Easy 레벨 문제풀이를 위한 Clojure 문법 ====== 
  
- 
-==== 키워드 자료형 ==== 
- 
-키워드(Keyword)는 Java의 Enum 과 같은 개념으로 생각하면 된다. 즉 임의의 상수이다. 
-:으로 시작하는 임의의 문자열은 키워드이다. 
- 
-<code clojure> 
-:a  
-:1  
-:@ 
-</​code>​ 
- 
-==== Boolean과 Equality ==== 
- 
-Clojure에서 참/​거짓을 나타내는 논리형 데이타는 true와 false 이다. 
- 
-<code clojure> 
-(= 1 1) ;==> true 
-(= 1 2) ;==> false 
- 
-(if true 1 2) ;==> 1 
-(if false 1 2) ;==> 2 
-(= true (not false)) ;==> true 
-</​code>​ 
- 
- 
-false 과 nil 이외의 모든 값은 참이다. 
- 
-<​code ​ clojure> 
-(if false 1 2) ;==> 2 
-(if nil 1 2) ;==> 2 
- 
-(if 0 1 2) ;==> 1    0은 숫자 
-(if 1 1 2) ;==> 1    1은 숫자 
-(if ""​ 1 2) ;==> 1   ""​ empty string 
-(if \A 1 2) ;==> 1   \A 는 문자(Character) 
-(if [] 1 2) ;==> 1   [] empty vector 
-</​code>​ 
- 
- 
-==== 변환 (int/float) ==== 
- 
-  (int 1)   ;​=>​ 1 
-  (int 1M)  ;=> 1 
-  (int 1.2) ;=> 1 
-  (int \1)  ;=> 49 
-  (int \a)  ;=> 97 
- 
-  (float 1) ;=> 1.0 
-==== Java Interop ==== 
- 
-Clojure는 Java 코드를 그대로 가져다 사용할 수 있는 방식을 제공하는데,​ 이것을 Java Interop이라고 한다. \\ 
-Clojure의 문자는 Java의 Character 인스턴스에,​ 스트링은 Java의 String 인스턴스이다. \\ 
-Java 오브젝트의 메소드를 다음과 같이 호출할 수 있다. 
- 
-<code clojure> 
-(.toUpperCase "​abc"​) ;==> "​ABC"​ 
-</​code>​ 
- 
-클래스의 정적 메소드는 다음과 같이 호출할 수 있다. 
- 
-<code clojure> 
-(Character/​isUpperCase \A) ;==> true 
-</​code>​ 
- 
-==== 함수 호출 ==== 
- 
-Clojure는 Lisp이기 때문에 괄호를 사용한다. \\ 
-괄호의 첫 요소는 함수이고,​ 나머지는 파라미터이다. 
- 
-<code clojure> 
-(str "Hello " "​World!"​) ;==> "Hello World!"​ 
-</​code>​ 
- 
-따라서 수치연산 함수는 전위연산자이다. 
- 
-<code clojure> 
-(+ 1 1) ; => 2 
-(- 2 1) ; => 1 
-(* 1 2) ; => 2 
-(/ 2 1) ; => 2 
- 
-(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 
-</​code>​ 
- 
- 
-==== 익명 함수 ==== 
- 
-<code clojure> 
-(fn [s] (println "​hello,​ " s)) 
-#(println "​hello,​ " %) 
- 
-(#(* % %) 5) ;==> 25 
-((fn [n] (* n n)) 5) ;==> 25 
- 
-(#(* %1 %2) 5 4) ;==> 20 
-((fn [x y] (* x y)) 5 4) ;==> 20 
-</​code>​ 
- 
-==== 자료 구조 ==== 
- 
-Clojure에는 4개의 자료 구조가 있다 : List, Vector, Set, Map 
- 
- 
-<code clojure> 
-(1 2 3)  ; 리스트는 ()로 묶는다. 순서가 있으며 index를 통한 임의 접근이 않된다. 
-[1 2 3]  ; 벡터는 []로 묶는다. 순서가 있으며 index를 통한 임의 접근이 된다. 
-#{1 2 3} ; 집합은 #{}로 묶는다. 순서가 없으며 value를 통한 접근이 된다. value는 중복값을 가질 수 없다. 
-{:a 1 :b 2 :c 3}  ; 맵은 {}로 묶는다. 순서가 없으며 key를 통한 접근이 된다. key는 중복값을 가질 수 없다. 
-</​code>​ 
- 
-리스트를 제외한 나머지 자료구조는 인덱스나 키로 요소를 가져올 수 있다. 
- 
-<code clojure> 
-; 벡터는 인덱스로 값을 가져온다. 
-([1 2 3] 0) ;=> 1 ; 벡터의 첫 요소는 0는 인덱스 번호 0이다. 
-([1 2 3] 3) ;=> nil ; 인덱스 번호 3은 네번째 요소로 존재하지 않는다. 
- 
-; 맵은 키로 값을 가져온다. 
-({:a 1 :b 2 :c 3} :a) ;=> 1   ;​=>​ :a키에 해당하는 값은 1이다. 
-({:a 1 :b 2 :c 3} :d) ;=> nil ;=> :d라는 키는 없기 때문에 nil을 리턴 
-({:a 1 :b 2 :c 3} :d 4) ;=> 4 ;=> 맵에 해당키가 없는 경우 디폴트 값을 지정할 수 있다. 
- 
-; 집합은 요소 자신을 통해 값을 가져온다. (결국 존재여부 확인) 
-(#{1 2 3} 1) ;=> 1  ; 집합은 값과 키가 같은 맵이라고 생각하면 된다. 앞의 집합은 {1 1 2 2 3 3} 맵으로 생각할 수 있다. 
-(#{1 2 3} 0) ;=> nil ; 앞의 집합에서 1은 있으나 0은 없다. 
-</​code>​ 
- 
-get 함수를 통해 명시적으로 요소를 가져올 수 있다. 
- 
-<code clojure> 
-(get [1 2 3] 0) ;=> 1 ; 인덱스는 0부터 시작한다. 
- 
-(get {:a 1 :b 2 :c 3} :a) ;=> 1    
-(get {:a 1 :b 2 :c 3} :d) ;=> nil  
-(get {:a 1 :b 2 :c 3} :d 4) ;=> 4 ; 4는 디폴트 값. 
- 
-(get #{1 2 3} 1) ;=> 1  ​ 
-(get #{1 2 3} 0) ;=> nil 
-</​code>​ 
- 
-get 함수를 통하면 벡터와 집합에 해당 요소가 없을 경우 디폴트 값을 지정할 수 있다. 
- 
-<code clojure> 
-(get [1 2 3] 3) ;=> nil 
-(get [1 2 3] 3 100) ;=> 100 
- 
-(get #{1 2 3} 0) ;=> nil 
-(get #{1 2 3} 0 100) ;=> 100 
-</​code>​ 
- 
-맵에서 해당키의 값이 nil일 경우, contains?​로 키의 존재 여부를 확인할 수 있다. 
- 
-<code clojure> 
-({:a nil} :b) => nil 
-({:a nil} :a) => nil 
-(contains? {:a nil} :a) ;=> true 
-</​code>​ 
- 
-벡터는 nth로도 값을 가져올 수 있다. 
- 
-<code clojure> 
-(nth [1 2 3] 0) ;=> 1 
-(nth [1 2 3] 3) ;=> 예외(IndexOutOfBoundsException) 발생 
-(nth [1 2 3] 3 3) ;=> 3 
-</​code>​ 
- 
-==== 생성 함수(list/​vector/​hash-set/​hash-map) ==== 
- 
-  (list 1 2 3)             ;​=>​ (1 2 3) 
-  (vector 1 2 3)           ;​=>​ [1 2 3] 
-  (hash-set 1 1 2 2 2 3 3) ;=> #{1 2 3} 
-  (hash-map :a 1 :b 2)     ;​=>​ {:a 1 :b 2} 
-  ​ 
-==== vec/vector ==== 
- 
-**vec** \\ 
-리스트/​맵/​집합을 벡터로 바꾼다. 
- 
-  (vec '(1 2 3)) ;=> [1 2 3] 
-  (vec #{1 2 3}) ;=> [1 2 3] 
-  (vec {:a 1 :b 2 :c 3}) ;=> [[:c 3] [:b 2] [:a 1]] 
- 
-**vector** \\ 
-인자들로 구성된 벡터를 만든다. 
-  ​ 
-  (vector 1 2 3) ;=> [1 2 3] 
-  ​ 
-==== 자료구조에 추가/​삭제 : cons/​conj/​pop/​disj/​assoc/​dissoc/​assoc-in ==== 
- 
-=== 리스트에 추가 === 
- 
-<code clojure> 
-(cons 0 '(1 2 3)) ;=> (0 1 2 3) 
-(conj '(1 2 3) 4) ;=> (4 1 2 3) 
-(pop '(1 2 3)) ;=> (2 3) 
-</​code>​ 
- 
-Clojure는 코딩시 (1 2 3) 하면 위에서 함수를 설명한 것처럼 괄호()의 첫 요소인 1을 함수로 평가하게 되는데, 1은 함수가 아니기 때문에 예외가 발생한다. Clojure 컴파일러가 괄호()를 평가하지 않고 그냥 리스트로 인식하게 하기 위해서는 '(1 2 3) 처럼 하면 된다. 
- 
-cons는 새로운 리스트를 만든다. 새로운 리스트의 첫 요소는 첫번째 파라미터이고,​ 나머지는 두번째 파라미터의 요소들이다. \\ 
-conj(oin)는 리스트에 새 요소를 추가하는데,​ 리스트에 추가하는 가장 빠른 방법은 앞에 추가하는 것이다. ​ 
- 
-=== 벡터에 추가 === 
- 
-<code clojure> 
-(cons 0 [1 2 3]) ;==> (0 1 2 3) 
-(conj [1 2 3] 4) ;==> [1 2 3 4] 
-(pop [1 2 3]) ;=> [1 2] 
-</​code>​ 
- 
-cons는 그 대상이 벡터여도 결과는 같다. 즉 맨 앞에 추가한 리스트를 리턴한다. \\ 
-conj는 벡터일 때는 맨 뒤에 추가한다. 벡터는 인덱스 접근이 가능하기 때문이다. 
- 
- 
-=== 집합에 추가/​삭제 === 
- 
-<code clojure> 
-(conj #{1 2 3} 4) ;=> #{1 2 3 4} ; 추가 
-(disj #{1 2 3} 3) ;=> #{1 2}     ; 삭제 
-</​code>​ 
- 
-=== 맵에 추가/​삭제 === 
- 
-<code clojure> 
-(assoc {:a 1} :b 2) ;=> {:a 1 :b 2} ; 추가 
-(assoc {:a 1} :b 2 :c 3 :d 4) ;=> {:a 1 :b 2 :c 3} ; 추가 
-(dissoc {:a 1 :b 2} :b) ;=> {:a 1}  ; 삭제 
- 
-</​code>​ 
- 
-==== assoc-in / update-in ==== 
- 
-<code clojure> 
-(assoc-in {:a {:x 1}} [:a :x] 100) ;=> {:a {:x 100}} 
-(update-in {:a {:x 1}} [:a :x] inc) ;=> {:a {:x 2}} 
- 
-</​code>​ 
-==== 자료 구조에 접근하는 함수 : first/​second/​last/​rest ==== 
- 
-<code clojure> 
-(first '(1 2 3 4 5)) ;=> 1 
-(second '(1 2 3 4 5)) ;=> 2 
-(last '(1 2 3 4 5)) ;=> 5 
-(rest '(1 2 3 4 5)) ;=> (2 3 4 5) 
-</​code>​ 
- 
-==== ffirst/​next/​butlast/​fnext/​nfirst === 
- 
-<code clojure> 
-(ffirst [[1] [2]]) ;=> 1 ;(first (first x)) 와 같다 
-(next [1 2 3 4 5]) ;=> (2 3 4 5) ;rest와 같다. 마지막 요소가 없으면 nil을 리턴 
-(next []) ;=> nil 
-(butlast [1 2 3 4 5]) ;=> (1 2 3 4) ;​마지막을 제외한 리스트 
-(fnext [1 2 3]) ;=> 2 ;(first (next x)) 와 같다. 
-(nfirst [[1 2] 3]) ;=> 2 ;(next (first x)) 와 같다. 
-</​code>​ 
- 
-==== rest와 next의 차이 ==== 
- 
-<code clojure> 
-(rest [1 2 3]) ;=> (2 3) 
-(next [1 2 3]) ;=> (2 3) 
- 
-(rest []) ;=> () 
-(next []) ;=> nil 
-</​code>​ 
- 
-==== seq / empty? ==== 
- 
-**(empty? coll)** \\ 
-coll이 비었으면 true, 아니면 false를 반환한다. 
- 
-  (empty? ())   ;​=>​ true 
-  (empty? '(1)) ;=> false 
-  (empty? nil)  ;=> true 
- 
- 
-**(seq coll)** \\ 
-coll의 seq를 반환한다. 
- 
-  (seq '​(1)) ​ ;=> (1) 
-  (seq [1 2]) ;=> (1 2) 
-  (seq "​abc"​) ;=> (\a \b \c) 
- 
-  (seq nil)   ;​=>​ nil 
-  (seq '​()) ​  ;​=>​ nil 
-  (seq ""​) ​   ;=> nil 
- 
-coll이 비었거나 nil은 경우를 확인하기 위해서는 seq를 쓰는 것이 좋다. 
- 
- 
-==== contains? ==== 
- 
-**(contains?​ coll key)** \\ 
-컬렉션 coll에 key가 있는지 여부 판단. 
- 
-  (contains? {:a 1} :a)    ;=> true 
-  (contains? {:a nil} :a)  ;=> true 
-  (contains? {:a 1} :b)    ;=> false 
- 
-  (contains? [:a :b :c] :b)  ;=> false 
-  (contains? [:a :b :c] 2)   ;​=>​ true 
- 
-  (contains? #​{"​a"​ "​b"​ "​c"​} "​a"​) ;=> true 
-  (contains? #​{"​a"​ "​b"​ "​c"​} "​z"​) ;=> false  ​ 
-  ​ 
-==== range ==== 
- 
-** (range)(range end)(range start end)(range start end step) ** \\ 
-[start end) 사이의 정수로 된 지연 시퀀스를 반환한다. setp만큼 건너뛴다. 
- 
- 
-  (range 10) 
-  ;=> (0 1 2 3 4 5 6 7 8 9) 
-  ​ 
-0부터 시작해서 인수만큼의 정수의 리스트를 만든다. 
- 
-  (range -5 5) 
-  ;=> (-5 -4 -3 -2 -1 0 1 2 3 4) 
-  ​ 
-  (range -0 100 10) 
-  ;=> (0 10 20 30 40 50 60 70 80 90) 
-  ​ 
-  (range 100 0 -10) 
-  ;=> (100 90 80 70 60 50 40 30 20 10) 
- 
-시작과 끝, 그리고 step을 지정할 수 있다. 
-  ​ 
-  (range) ​ 
-  ;=> (0 1 2 3 4 5 6 7 8 9 10 ... 12770 12771 12772 12773 ... n 
-  ​ 
-  (take 10 (range)) 
-  ;=> (0 1 2 3 4 5 6 7 8 9) 
-  ​ 
-(range)는 0을 포함한 자연수의 집합이라는 무한 지연 시퀀스를 만든다.\\ 
-이것을 실행하면 무한 반복되어 그 스레드는 먹통이 된다. \\ 
-그래서 take로 잡아주어야 한다. 
-==== if / when ==== 
- 
-**if** 
- 
-  (if true 1 2)  ;=> 1 
-  (if false 1 2) ;=> 2 
-  (if fasel 1)   ;​=>​ nil 
- 
-**when** 
- 
-  (when (= 1 1) true)    => true 
-  (when (not= 1 1) true) => nil 
-  ​ 
-==== cond / case / condp ==== 
- 
-**cond** \\ 
-여러 조건절에 따라 분기 
- 
-  (let [grade 85] 
-    (cond 
-      (>= grade 90) "​A"​ 
-      (>= grade 80) "​B"​ 
-      (>= grade 70) "​C"​ 
-      (>= grade 60) "​D"​ 
-      else "​F"​)) 
-   ;​=>​ "​B"​ 
- 
-**case** \\ 
-경우에 따라 분기 
- 
-  (let [x 2] 
-     (case x 
-       1 10 
-       2 20 
-       3 30 
-       "​none"​)) 
-  ;=> 20 
- 
-**condp** \\ 
-pred 평가에 따른 분기 
- 
-  (let [x 2] 
-   ​(condp = x 
-        1 "​one"​ 
-        2 "​two"​ 
-        3 "​three"​ 
-        (str "​unexpected value, \""​ x \"))) 
-        ​ 
- 
-==== reverse ==== 
- 
-**(reverse coll)** \\ 
-역전된 coll을 반환한다. 
- 
-  (reverse '(1 2 3)) ;=> (3 2 1) 
-  ​ 
-==== take/drop ==== 
- 
-**(take n coll)** \\ 
-coll의 처음 n개의 요소로 된 lazy-seq를 리턴한다. 
- 
-<code clojure> 
-(take 3 '(1 2 3 4 5 6)) ;=> (1 2 3) ; 리스트를 받아 lazy-seq를 리턴 
-(take 3 [1 2 3 4 5 6) ;=> (1 2 3)   ; 벡터를 받아 lazy-seq를 리턴 
-(take 3 [1 2]) ;=> (1 2)  ​ 
-</​code>​ 
- 
-(drop n coll) \\ 
-coll의 처음 n개의 요소를 제외한 나머지로 된 lazy-seq를 리턴한다. 
- 
-<code clojure> 
-(drop 3 '(1 2 3 4 5 6)) ;=> (4 5 6) 
-(drop 3 [1 2 3 4 5 6]) ;=> (4 5 6) 
-(drop 3 [1 2]) ;=> ()  ​ 
-</​code>​ 
- 
-==== take-while/​drop-while ==== 
- 
-**(take-while pred coll)** \\ 
-(pred el)이 참인 동안의 요소들로 된 lazy-seq를 리턴한다. 즉 처음 (pred el)이 거짓일 때까지의 요소로 된 lazy-seq. 
- 
-<code clojure> 
-(take-while neg? [-2 -1 0 1 2 3]) ;=> (-2 -1) 
-(take-while neg? [-2 -1 0 -1 -2 3]) ;=> (-2 -1) 
-</​code>​ 
- 
-**(drop-while pred coll)** \\ 
-(pred el)이 참인 동안의 요소들을 제외한 나머지 요소로 된 lazy-seq를 리턴한다. 즉 처음 (pred el)이 거짓일 때까지의 요소 제외한 lazy-seq. 
- 
-<code clojure> 
-(drop-while neg? [-1 -2 -6 -7 1 2 3 4 -5 -6 0 1]) ;=> (1 2 3 4 -5 -6 0 1) 
-</​code>​ 
- 
-==== map ==== 
- 
-**(map f coll)** \\ 
-map 함수는 다음과 같이 수학에서 한 집합에서 다른 집합으로 바꾸는 작업을 한다. f는 coll의 각 요소에 적용된다. 
- 
-     ​X ​                ​Y ​   
-   ​+----+ ​  (f x1)   ​+----+ 
-   | x1 |  -------> ​ | y1 | 
-   ​| ​   |   (f x2)   ​| ​   | 
-   | x2 |  -------> ​ | y2 | 
-   ​| ​   |   (f x3)   ​| ​   | 
-   | x3 |  -------> ​ | y3 | 
-   ​| ​   |   (f x3)   ​| ​   | 
-   | x4 |  -------> ​ | y4 | 
-   ​+----+ ​           +----+ 
-    
-  ​ 
-f가 inc이고 coll [1 2 3 4]인 경우 coll의 모든 요소에 inc가 적용된 lazy-seq가 리턴된다. 
-  
-<code clojure> 
-(map inc [1 2 3 4])  ;=> (2 3 4 5) 
-</​code>​ 
- 
-     ​X ​               Y    
-   ​+---+ ​ (inc 1)   +---+ 
-   | 1 | --------> ​ | 2 | 
-   ​| ​  ​| ​ (inc 2)   ​| ​  | 
-   | 2 | --------> ​ | 3 | 
-   ​| ​  ​| ​ (inc 3)   ​| ​  | 
-   | 3 | --------> ​ | 4 | 
-   ​| ​  ​| ​ (inc 4)   ​| ​  | 
-   | 4 | --------> ​ | 5 | 
-   ​+---+ ​           +---+ 
- 
-map 함수는 clojure programming에서 가장 많이 사용하는 함수이고 기능도 아주 다양하다. 
-clojuredocs.org에는 map함수를 활용하는 다양한 예제 샘플들이 아주 많다. 
- 
-==== filter/​remove ==== 
- 
-**(filter pred coll)** \\ 
-filter 함수는 coll의 요소 el에 대해 (pred el)이 참인 el들로 된 lazy-seq를 리턴한다. 
- 
-     ​X ​                             Y    ​ 
-   ​+----+ ​   (pred x1) = true     ​+----+ 
-   | x1 |------------------------>​| x1 | 
-   ​| ​   |    (pred x2) = false    |    | 
-   | x2 |-----------------------x |    | 
-   ​| ​   |    (pred x3) = true     ​| ​   | 
-   | x3 |------------------------>​| x2 | 
-   ​| ​   |    (pred x4) = false    |    | 
-   | x4 |-----------------------x |    | 
-   ​+----+ ​                        ​+----+ 
-    
-<code clojure> 
-(filter even? (range 10)) ;=> (0 2 4 6 8) 
-</​code>​ 
- 
-remove는 반대이다. 즉 (pred el)이 참이면 제거한다. 
- 
-<code clojure> 
-(remove even? (range 10)) ;=> (1 3 5 7 9) 
-</​code>​ 
- 
- 
-==== keep ==== 
- 
-**(keep f coll)** \\ 
-keep 함수는 coll의 요소 el에 대해 (f el)이 nil이 아닌 리턴값으로 된 lazy-seq를 리턴한다. 
- 
-     ​X ​                        ​Y ​   ​ 
-   ​+----+ ​   (f x1) = y1     ​+----+ 
-   | x1 |------------------->​| y1 | 
-   ​| ​   |    (f x2) = nil    |    | 
-   | x2 |------------------x |    | 
-   ​| ​   |    (f x3) = y3     ​| ​   | 
-   | x3 |------------------->​| y3 | 
-   ​| ​   |    (f x4) = nil    |    | 
-   | x4 |------------------x |    | 
-   ​+----+ ​                   +----+ 
- 
-<code clojure> 
-(keep #(if (odd? %) %) (range 10)) ;=> (1 3 5 7 9) 
-</​code>​ 
-==== reduce ==== 
- 
-**(reduce f initial coll)** \\ 
-reduce 함수는 coll의 요소 el에 대해 2개의 인수를 받는 함수 (f acc el)의 결과를 다음 el들의 f의 acc에 적용하여 누적한 최종값(acc)을 리턴한다. 
- 
- 
-    
-   (f initial x0) ;=> acc1 
-       ​|---------------| 
-       v 
-   (f acc1 x1)    ;=> acc2 
-       ​|---------------| 
-       ​v ​   
-   (f acc2 x2)    ;=> acc3 
-       ​|---------------| 
-       v 
-   (f accn xn)    ;=> acc (최종값) 
-    
-    
-initial이 주어지지 않으면 최초 f 호출시 첫요소 x0가 acc로, x1은 el로 해서 호출된다. 
- 
-<code clojure> 
-(reduce + [1 2 3 4 5]) ;=> 15 
-</​code>​ 
- 
-위 reduce가 수행되는 과정은 다음과 같다. 
- 
-initial이 주어지지 않아서 처음 acc는 1이고, 2는 두번째 파라미터가 된다. 
- 
-   (+ 1 2)   ;​=>​ 3 
-      |----------| 
-      v 
-   (+ 3 3)   ;​=>​ 6 
-      |----------| 
-      v    
-   (+ 6 4)   ;​=>​ 10 
-      |-----------| 
-      v 
-   (f 10 5)  ;=> 15 (최종값) 
- 
-reduce는 매우 강력한 함수이다. 이것만 잘 사용하면 왠만한 제어구조는 거의 소화할 수 있다. 
- 
-(reduce에서 reduce를 사용하는 매우 복잡한 일도 가능하게 되는데, 가급적 사용하지 않는 것이 코드의 가독성을 키우는데 좋다.) 
- 
- 
-==== into ==== 
- 
-**(into to from)** \\ 
-from 컬렉션의 요소들을 to 컬렉션에 넣는다. 
- 
- 
-  (into [1 2 3] '(4 5 6))   ;​=>​ [1 2 3 4 5 6] 
- 
- 
-  (into [] {:a 1 :b 4})     ;​=>​ [[:a 1] [:b 2]] 
- 
- 
-  (into {} [[:a 1] [:b 2]]) ;=> {:a 1 :b 2} 
-  ​ 
-==== merge / merge-with ==== 
- 
-**(merge & maps)** \\ 
-맵들을 합친다. 키가 겹치면 나중의 것을 취한다. 
- 
-  (merge {:a 1 :b 2 :c 3} {:b 9 :d 4}) ;=> {:d 4, :a 1, :b 9, :c 3} 
-  ​ 
-**(merge-with f & maps)** \\ 
-맵들을 합친다. 키가 겹치면 그 값들을 함수 f에 적용한 값을 취한다. 
- 
-  (merge-with + {:a 1  :b 2} {:a 10  :b 20 :c 30}) ;=> {:a 11 :b 22 :c 30} 
-==== let 문구 ==== 
- 
-로컬 바인딩 
- 
-  (let [x 1]  
-    x) 
-  ;=> 1 
- 
- 
-  (let [a 1 b 2]  
-    (+ a b)) 
-  ;=> 3 
- 
-  (let [x 10 
-        y (range 10)]  
-    (apply + y)) 
-  ;=> 45 
- 
-==== loop recur ==== 
- 
-loop은 바인딩을 제공하고 recur는 loop으로 돌아가서 재바인딩한다. 
- 
-  (loop [x 0]         ; 1) 
-    (if (< x 10)      ; 2) 
-      (recur (inc x)) ; 3) 
-      x))             ; 4) 
- 
-  - 최초 x는 0이다. 
-  - loop을 빠져나오는 조건을 만든다. 
-  - x를 1증가시킨 후, 그 값을 다시 loop의 x에 바인딩한다. 
-  - x가 리턴된다. 
- 
-  (loop [sum 0 cnt 10]                  ; 1) 
-      (if (= cnt 0)                     ; 2) 
-        sum                             ; 3) 
-        (recur (+ cnt sum) (dec cnt)))) ; 4) 
- 
- 
-  - 최초 sum은 0, cnt는 10이다. 
-  - loop을 빠져나오는 조건을 만든다. 
-  - sum이 리턴된다. 
-  - sum과 cnt의 합이 sum으로 바인딩되고,​ cnt를 하나 줄여서 cnt에 바인딩된다. 
- 
-==== for ==== 
- 
-<code clojure> 
-(for [n (range 5)] 
- n) 
-;=> (0 1 2 3 4) 
-</​code>​ 
- 
-<code clojure> 
-(for [n (range 5)] 
- (+ n n) 
-;=> (0 2 4 6 8) 
-</​code>​ 
- 
-<code clojure> 
-(for [x ['a 'b '​c] ​ 
-      y [1 2 3]] 
-  [x y]) 
-;=> ([a 1] [a 2] [a 3] [b 1] [b 2] [b 3] [c 1] [c 2] [c 3]) 
-</​code>​ 
- 
-clojure에서 for는 제어구조가 아니라 매크로다. 그리고 리스트를 리턴한다. 이것이 다른 언어와 다른 점이다. 
- 
-for는 매우 막강한 기능을 갖는다. clojuredoc.org의 for 예제 샘플은 for의 막강한 기능을 잘 보여준다. 
- 
-(참고: http://​programming-puzzler.blogspot.kr/​2013/​03/​logic-programming-is-overrated.html) 
- 
-다음은 그중 일부이다. 
- 
-<code clojure> 
-(for [x [0 1 2 3 4 5] 
-      :let [y (* x 3)] 
-      :when (even? y)] 
-  y) 
-;=> (0 6 12) 
-</​code>​ 
- 
-<code clojure> 
-(for [x (range 1 6)  
-      :let [y (* x x)  
-            z (* x x x)]]  
-   [x y z])          ​ 
-;=> ([1 1 1] [2 4 8] [3 9 27] [4 16 64] [5 25 125]) 
-</​code>​ 
- 
-==== iterate /repeat ==== 
- 
-**(iterate f x)** \\ 
-x, (f x), (f (f x))의 지연 시퀀스를 만든다. 
- 
- 
-  (take 5 (iterate inc 5)) ;=> (5 6 7 8 9) 
- 
- 
-**(repeat x) (repeat n x)** \\ 
-주어진 값을 반복하는 지연 시퀀스를 만든다. 
-  
- 
-  (take 5 (repeat "​x"​)) ;=> ("​x"​ "​x"​ "​x"​ "​x"​ "​x"​) 
- 
-  (repeat 5 "​x"​) ​       ;=> ("​x"​ "​x"​ "​x"​ "​x"​ "​x"​) 
- 
-==== apply ==== 
- 
-**(apply f args)** \\ 
-함수 f를 args에 적용한다. 
- 
-  (+ 1 2 3)          ;=> 6 
-  (apply + '(1 2 3)) ;=> 6 
- 
- 
-  (max 1 2 3)          ;=> 3 
-  (apply max '(1 2 3)) ;=> 3 
-  ​ 
-==== partial ==== 
- 
-**(partial f)(partial f arg1)(partial f arg1 arg2) ... ** \\ 
-함수 f와 f의 일부 인수를 받고 함수를 반환하는데,​ 이 반환함수는 f의 나머지 인수를 받아서 f 함수를 수행할 수 있다. 
- 
-  (def add5 (partial + 5)) 
-  (add5 1) ;=> 6 
-  (add5 1 2) ;=> 8 
- 
-  (def my-hello (partial str "​Hello"​ ", ")) 
-  (my-hello "​john"​) 
-  (my-hello "​john"​ " and " "​sujan"​) 
- 
-==== comp ==== 
- 
-**(comp f g)** \\ 
-합성함수 f(g)를 만든다. 
- 
-  ((comp str +) 8 8 8)   ;​=>​ "​24"​ 
- 
-  (filter (comp not zero?) [0 1 0 2 0 3 0 4]) ;=> (1 2 3 4) 
- 
-==== concat / mapcat ==== 
- 
-**(concat x y)(concat x y & zs)** \\ 
-컬렉션들을 합친다. 
- 
-  (concat [1 2] [3 4]) ;=> (1 2 3 4) 
- 
-  (concat "​abc"​ "​def"​) ;=> (\a \b \c \d \e \f) 
- 
-  (apply concat '(([1 2]) ([3 4] [5 6]) ([7 8]))) 
-  ;=> ([1 2] [3 4] [5 6] [7 8]) 
- 
- 
-**(mapcat f & colls)** \\ 
-일반적인 map을 수행한 후, concat을 적용한다. f는 컬렉션을 반환해야 한다. 
- 
-  (mapcat reverse [[3 2 1 0] [6 5 4] [9 8 7]]) 
-  ;=> (0 1 2 3 4 5 6 7 8 9) 
- 
-==== some / every? ==== 
- 
-**(some pred coll)** \\ 
-coll의 요소 x에 대해 (f x)가 논리적으로 참일 때의 반환값을 반환한다. 
- 
-  (some even? '(1 2 3 4))         ;​=>​ true 
-  (some true? [false true false]) ;=> true  ​ 
-  (some #(= 5 %) [1 2 3 4 5])     ;​=>​ true 
- 
-  (some #(when (even? %) %) '(1 2 3 4)) ;=> 2 
-  (some #{2 4 6} [0 1 2 3 4 5])         ;​=>​ 2 
- 
- 
-**(every? pred coll)** \\ 
-coll의 모든 요소 x에 대해 (pred x)가 참이면 true, 아니면 false를 반환한다. 
- 
-  (every? even? '(2 4 6)) ;=> true 
-  (every? even? '(1 2 3)) ;=> false 
- 
- 
-  (every? #{1 2} [1 2 3]) ;=> false 
-  (every? #{1 2} [1 2])   ;​=>​ true 
- 
- 
-==== -> / ->> threading form ==== 
- 
-thread-first form 
- 
-  (first (.split (.replace (.toUpperCase "a b c d") "​A"​ "​X"​) " ")) 
-  ;=> "​X"​ 
- 
-코드상 함수의 위치 순서와 실행 순서가 반대라서 코드를 이해하기 어렵다. 
- 
-  (-> "a b c d" ​ 
-      .toUpperCase ​ 
-      (.replace "​A"​ "​X"​) ​ 
-      (.split " "​) ​ 
-      first) 
-  ;=> "​X"​ 
- 
-코드상 함수가 그 실행 순서대로 배치되어 있어 이해하기가 쉽다. 
- 
-thread-last form 
- 
-  (reduce + (take 10 (filter even? (map #(* % %) (range))))) 
-  ​ 
-  (->> (range) 
-       (map #(* % %)) 
-       ​(filter even?) 
-       (take 10) 
-       ​(reduce +)) 
-  ;=> 1140 
-  ​ 
-==== mod / quot ==== 
- 
-  (mod 10 6)  ;=> 4, 나머지 
-  (quot 10 3) ;=> 3, 몫 
- 
-==== identity ==== 
- 
-**(identity x)** \\ 
-받은 인수를 그래로 반환한다. 
- 
-  (identity 4) ;=> 4 
- 
-==== interleave / interpose ==== 
- 
-**(interleave c1 c2)** \\ 
-각 컬렉션의 요소들을 순서대로 섞는다. 
- 
-  (interleave [:a :b :c] [1 2 3]) ;=> (:a 1 :b 2 :c 3) 
- 
-**(interpose sep coll)** \\ 
-coll의 요소 사이에 sep을 넣는다. 
- 
-  (interpose 0 [1 2 3]) ;=> (1 0 2 0 3) 
-==== partition / partition-by ==== 
- 
-**(partition n coll) (partition n step coll) (partition n step pad coll)** \\ 
-아이템을 n개씩 묶는다. step만큼 건너뛰면서. 
- 
-  (partition 2 (range 10)) 
-  ;=> ((0 1) (2 3) (4 5) (6 7) (8 9)) 
- 
-  (partition 4 (range 11)) 
-  ;=> ((0 1) (2 3) (4 5) (6 7) (8 9)) 
- 
-  (partition 2 1 (range 10)) 
-  ;=> ((0 1) (1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8) (8 9)) 
- 
-  (partition 4 6 ["​a"​ "​b"​ "​c"​ "​d"​] (range 20)) 
-  ;=> ((0 1 2 3) (6 7 8 9) (12 13 14 15) (18 19 "​a"​ "​b"​))  ​ 
- 
- 
-**(partition-by f coll)** \\ 
-f함수의 반환값에 따라 아이템을 묶는다. 
- 
-  (partition-by #(= 3 %) [1 2 3 4 5])  
-  ;=> ((1 2) (3) (4 5)) 
- 
-  (partition-by odd? [1 1 1 2 2 3 3]) 
-  ;=> ((1 1 1) (2 2) (3 3)) 
- 
-  (partition-by identity "​ABBA"​) 
-  ;=> ((\A) (\B \B) (\A)) 
- 
-==== group-by ==== 
- 
-**(group-by f coll)** \\ 
-함수 f의 반환값이 같은 것끼리 묶는다. 
- 
-  (group-by odd? (range 10)) 
-  ;=> {false [0 2 4 6 8], true [1 3 5 7 9]} 
- 
-  (group-by count ["​a"​ "​as"​ "​asd"​ "​aa"​ "​asdf"​ "​qwer"​]) 
-  ;=> {1 ["​a"​],​ 2 ["​as"​ "​aa"​],​ 3 ["​asd"​],​ 4 ["​asdf"​ "​qwer"​]} 
-  ​ 
- 
-==== map-indexed / keep-indexed ==== 
- 
-**(map-indexed f coll)** \\ 
-map 과 같은데, 함수 f의 첫 인수로 인덱스이고,​ 두번째 인수가 coll의 요소(item)이다. 
- 
-  (map-indexed vector (range 10)) 
-  ;=> ([0 0] [1 1] [2 2] [3 3] [4 4] [5 5] [6 6] [7 7] [8 8] [9 9]) 
- 
-  (map-indexed (fn [idx itm] [idx itm]) "​foobar"​) 
-  ;=> ([0 \f] [1 \o] [2 \o] [3 \b] [4 \a] [5 \r]) 
- 
- 
-**(keep-indexed f coll)** \\ 
-keep 과 같은데, 함수 f의 첫 인수로 인덱스이고,​ 두번째 인수가 coll의 요소(item)이다. 
- 
-  (keep-indexed #(if (odd? %1) %2) [:a :b :c :d :e]) 
-  ;=> (:b :d) 
- 
- 
-==== lazy-seq ==== 
- 
-지연 시퀀스를 만든다. 
- 
-  (defn fib [a b] (lazy-seq (cons a (fib b (+ b a))))) 
-  (take 5 (fib 1 1))  ;=> (1 1 2 3 5) 
-  ​ 
- 
-==== destructuring ==== 
lecture/4clojure/level-elementary-easy.txt · Last modified: 2019/02/04 14:26 (external edit)