-
Couldn't load subscription status.
- Fork 8
Living Clojure 01
Kyunggook Kim edited this page Aug 15, 2016
·
1 revision
- 자바 SDK 설치
- 클로저 REPL 준비
- wget https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
- chmod a+x lein
- mv lein /usr/local/bin
- lein
- lein new 프로젝트명
- cd 프로젝트명
- lein repl
42
;=> 42- REPL에 숫자 42를 입력하고 엔터키를 누른다.
- 이 식의 결과는 자기 자신이다(즉, 자기 자신으로 평가되어 42가 되었음을 의미한다).
- 그 식의 결과가 출력된다. 이 책에서 출력 결과는
;=>를 사용한다.
;; 실수값 입력
12.43
;=> 12.43
;; 분수가 평가될 때 실수로 변환 안됨
1/3
;=> 1/3
;; 분수에서 분모와 분자 간에 약분 가능
4/2
;=> 2
;; 분수의 분모와 분자에는 정수만 사용 가능
4.0/2
;=> NumberFomatException Invalid number: 4.0/2
;; 1을 3으로 나눔, 결과 또한 분수
(/ 1 3)
;=> 1/3
;; 인수 중 하나가 실수이기 때문에 결과 또한 실수
(/ 1 3.0)
;=> 0.3333333333333333- 클로저에서는 함수나 연산자가 먼저 오고, 필요한 인수가 뒤에 온다.
;; 클로저의 문자열은 큰따옴표로 둘러쌈
"jam"
;=> "jam"
;; 클로저에서 키워드는 콜론으로 시작하는 식별자
:jam
;=> :jam
;; 하나의 문자만 사용하는 경우 역슬래시 뒤에 문자를 붙임
\j
;=> \j
;; 자기 자신으로 평가되는 단순값. 불린(boolean)
true
;=> true
false
;=> false
;; 클로저에서 값이 없음을 표현
nil
;=> nil(+ 1 1)
;=> 2
(+ 1 (+ 8 3))
;=> 12- 식 내부에 식이 포함될 수 있고, 내부의 식이 먼저 평가되고, 그 다음 식이 평가된다.
- 리스트 컬렉션 사용하기
- 리스트의 특징은 요소들이 순서를 가진다.
- 리스트의 생성은 인용기호(
')를 괄호 앞에 붙이고 데이터를 괄호 안에 넣으면 된다.
;; 클로저에서는 문자열, 정수, 키워드 같은 여러 종류의 값을 컬렉션 안에 혼합가능
'(1 2 "jam" :marmalade-jar)
;=> (1 2 "jam" :marmalade-jar)
;; 요소들 사이에 쉼표가 있어도 쉼표는 공백 문자처럼 취급되어 무시
'(1, 2, "jam", :bee)
;=> (1 2 "jam" :bee)- 리스트로 무엇을 할 수 있을까?
-
first함수는 리스트의 첫 요소를 반환 -
rest함수는 첫 요소를 제외한 나머지 모든 요소들의 리스트를 반환 -
cons함수는 두 개의 인수, 첫째는 추가하고자 하는 요소, 둘째는 그 요소가 추가될 리스트 - 인용기호(
')와list함수로도 리스트 생성 가능
-
(first '(:rabbit :pocket-watch :marmalade-jar :door))
;=> :rabbit
(rest '(:rabbit :pocket-watch :marmalade-jar :door))
;=> (:pocket-watch :marmalade-jar :door)
(first (rest '(:rabbit :pocket-watch :marmalade-jar :door)))
;=> :pocket-watch
(first (rest (rest '(:rabbit :pocket-watch :marmalade-jar :door))))
;=> :marmalade-jar
(first (rest (rest (rest '(:rabbit :pocket-watch :marmalade-jar :door)))))
;=> :door
(first (rest (rest (rest (rest '(:rabbit :pocket-watch :marmalade-jar :door))))))
;=> nil
(cons 5 '())
;=> (5)
;; nil로 리스트 만들기
(cons 5 nil)
;=> (5)
(cons 4 (cons 5 nil))
;=> (4 5)
(cons 3 (cons 4 (cons 5 nil)))
;=> (3 4 5)
(cons 2 (cons 3 (cons 4 (cons 5 nil))))
;=> (2 3 4 5)
'(1 2 3 4 5)
;=> (1 2 3 4 5)
(list 1 2 3 4 5)
;=> (1 2 3 4 5)- 벡터를 사용해 인덱스로 데이터 접근하기
- 대괄호로 둘러싸서 만든다.
-
first,rest함수는 리스트와 동일하게 동작한다. -
nth함수를 통해 해당 인덱스에 있는 벡터의 요소에 접근할 수 있다. - 인덱스는 0번부터 시작한다.
-
last함수는 벡터의 마지막 요소를 반환한다. - 리스트는 처음 시작부터 원하는 요소까지 탐색하기 때문에 벡터의
nth와last가 성능이 더 좋다. - 따라서 인덱스로 컬렉션의 요소에 접근할 필요가 있다면 벡터를 쓴다.
[:jar1 1 2 3 :jar2]
;=> [:jar1 1 2 3 :jar2]
(first [:jar1 1 2 3 :jar2])
;=> :jar1
(rest [:jar1 1 2 3 :jar2])
;=> [1 2 3 :jar2]
(nth [:jar1 1 2 3 :jar2] 0)
;=> :jar1
(nth [:jar1 1 2 3 :jar2] 2)
;=> :jar2
;; 벡터에 last 적용
(last [:rabbit :pocket-watch :marmalade])
;=> :marmalade
;; 리스트에 last 적용
(last '(:rabbit :pocket-watch :marmalade))
;=> :marmalade- 컬렉션의 공통점들
- 모든 컬렉션은 불변(
immutable)이고 존속적(persistent)이다. - 불변은 컬렉션의 값이 변하지 않는다는 것을 의미한다.
- 요소를 컬렉션에 추가하면 새로 생성된 컬렉션이 반환된다.
- 존속이란 구조 공유(
structual sharing) 기법을 통해 효율적으로 만들어진다는 것을 의미한다.
- 모든 컬렉션은 불변(
;; count 함수는 컬렉션의 크기를 반환
(count [1 2 3 4])
;=> 4
;;`conj` 함수는 해당 데이터 구조에 가장 효율적인 방식으로 컬렉션에 요소를 추가한다.
;; conj는 벡터의 맨 뒤에 요소를 추가하여 새로운 벡터를 반환한다.
(conj [:toast :butter] :jam)
;=> [:toast :butter :jam]
;; 여러 개의 요소를 벡터의 맨 뒤에 추가하여 새로운 벡터를 반환한다.
(conj [:toast :butter] :jam :honey)
;=> [:toast :butter :jam :honey]
;; conj는 리스트의 맨 앞에 요소를 추가하여 새로운 리스트를 반환한다.
(conj '(:toast :butter) :jam)
;=> (:jam :toast :butter)
;; 여러 개의 요소를 리스트의 맨 앞에 추가하여 새로운 리스트를 반환한다.
(conj '(:toast :butter) :jam :honey)
;=> [:honey :jam :toast :butter)- 맵을 사용해 키-값 쌍의 데이터를 저장하기
- 맵은 중괄호로 둘러싼다.
- 가독성을 위해 맵에서 쉼표를 사용할 수 있다.
-
get함수로 맵에서 값을 가져올 수 있다. - 맵의 키가 키워드라면
get을 사용하지 않고 키 자체를 함수로 사용할 수 있다. -
keys함수는 맵의 키만을,vals함수는 맵의 값만을 반환한다. -
assoc함수는 맵에 새로운 키-값 쌍을 결합하여 새로운 맵을 반환한다. -
dissoc함수는 맵과 키를 인수로 받아 그 키-값 쌍이 제거된 새로운 맵을 반환한다. -
merge함수는 여러 맵의 키-값 쌍을 합쳐서 새로운 맵을 반환한다.
{:jam1 "strawberry" :jam2 "blackberry"}
;=> {:jam1 "strawberry", :jam2 "blackberry"}
{:jam1 "strawberry", :jam2 "blackberry"}
;=> {:jam1 "strawberry", :jam2 "blackberry"}
;; get을 명시적으로 사용한 예
(get {:jam1 "strawberry", :jam2 "blackberry"} :jam2)
;=> "blackberry"
;; 키가 없는 경우 디폴트 값
(get {:jam1 "strawberry", :jam2 "blackberry"} :jam3 "not found")
;=> "not found"
;; 키를 함수로 사용해 값 가져오기
(:jam2 {:jam1 "strawberry", :jam2 "blackberry", :jam3 "marmalade"})
;=> "blackberry"
;; keys 함수
(keys {:jam1 "strawberry", :jam2 "blackberry", :jam3 "marmalade"})
;=> (:jam1 :jam2 :jam3)
;; vals 함수
(vals {:jam1 "strawberry", :jam2 "blackberry", :jam3 "marmalade"})
;=> ("strawberry", "blackberry", "marmalade")
;; assoc 함수
(assoc {:jam1 "red", :jam2 "black"} :jam3 "orange")
;=> {:jam1 "red", :jam2 "black", :jam3 "orange"}
;; dissoc 함수
(dissoc {:jam1 "strawberry", :jam2 "blackberry"} :jam1)
;=> {:jam2 "blackberry"}
;; merge 함수
(merge {:jam1 "red" :jam2 "black"}
{:jam1 "orange" :jam3 "red"}
{:jam4 "blue"})
;=> {:jam1 "orange", :jam2 "black", :jam3 "red", :jam4 "blue"}- 집합을 사용해 유일한 데이터의 컬렉션 표현하기
- 집합은 요소의 중복이 없는 컬렉션을 만들 때 유용하다.
- 집합은
#{}로 둘러싼다. - 합집합, 차집합, 교집합 등의 집합 연산이 가능하다.
-
set함수를 이용해 다른 종류의 컬렉션을 집합으로 바꿀 수 있다.
#{:red :blue :white :pink}
;=> #{:white :red :blue :pink}
;; 집합을 생성할 때 중복은 허용되지 않는다.
#{:red :blue :white :pink :pink}
;=> IllegalArgumentException Duplicate key: :pink
;; 합집합
(clojure.set/union #{:r :b :w} #{:w :p :y})
;=> #{:y :r :w :b :p}
;; 차집합
(clojure.set/difference #{:r :b :w} #{:w :p :y})
;=> #{:r :b}
;; 교집합
(clojure.set/intersection #{:r :b :w} #{:w :p :y})
;=> #{:w}
;; 벡터를 집합으로 바꾸기(중복 제거됨)
(set [:rabbit :rabbit :watch :door])
;=> #{:door :watch :rabbit}
;; 맵을 집합으로 바꾸기
(set {:a 1 :b 2 :c 3})
;=> #{[:c 3] [:b 2] [:a 1]}
;; get 함수를 사용해서 요소 찾기
(get #{:rabbit :door :watch} :rabbit)
;=> :rabbit
(get #{:rabbit :door :watch} :jar)
;=> :nil
;; 키워드를 사용해서 요소 찾기
(:rabbit #{:rabbit :door :watch})
;=> :rabbit
;; 집합 자체를 함수로 사용해서 요소 찾기
(#{:rabbit :door :watch} :rabbit)
;=> :rabbit
;; contains?를 사용해서 요소가 있는지 확인
(contains? #{:rabbit :door :watch} :rabbit)
;=> true
(contains? #{:rabbit :door :watch} :jam)
;=> false
;; conj 함수를 사용해 집합에 요소 추가
(conj #{:rabbit :door} :jam)
;=> #{:door :rabbit :jam}
;; disj 함수는 집합에서 요소를 제거할 때 사용
(disj #{:rabbit :door} :door)
;=> #{:rabbit}- 단순값과 컬렉션에 대한 요약
- 문자열, 정수, 분수, 실수, 키워드, 문자, 불린은 함수나 식에서 사용될 수 있다.
- 클로저의 식에서는 연산자나 함수가 먼저 오고, 인수가 뒤따라온다.
- 리스트는 맨 앞에서부터 접근할 수 있는 데이터 컬렉션이다.
- 벡터는 임의의 위치로 접근할 수 있는 데이터 컬렉션이다.
- 맵은 키-값 쌍들로, 데이터를 구성하고 쉽게 접근하는 데 좋다.
- 집합은 유일한 요소들의 컬렉션으로, 집합 연산이 가능하다.