그 밖에 포함된 라이브러리들
그 밖에 포함된 라이브러리들 (Other Included Libraries)
본문
Java 유틸리티 (clojure.java.*)
초기 및 현재 런타임 기반(basis)에 대한 접근. 여기에는 JVM 클래스패스에 현재 로드된 라이브러리와 버전이 명시돼요.
Java 클래스로 뒷받침된 Clojure용 다형적(polymorphic) I/O 유틸리티 함수들을 포함해요.
클래스나 인스턴스 클래스에 적절한 Javadocs를 표시하려 시도하는 함수 javadoc를 제공해요.
서브프로세스 실행과 통신을 지원해요. 이 네임스페이스는 clojure.java.shell을 대체하며 최신 Java 프로세스 API를 사용해요.
서브프로세스 실행과 관리를 촉진하는 sh 함수를 제공해요. 예상 인자에 대한 자세한 내용은 함수 문서를 참고하세요.
병렬 처리 (Parallel Processing, DEPRECATED)
병렬 라이브러리(네임스페이스 parallel, parallel.clj에 있음)는 ForkJoin library를 감싸요. 이 lib는 이제 폐기(deprecated)됐어요.
기본 아이디어는, Clojure 컬렉션(가장 효율적으로는 벡터)이 이 라이브러리에서 사용하기 위해 par 함수로 병렬 배열(parallel array)로 바뀔 수 있다는 것이에요. 대부분의 함수는 컬렉션을 받고 필요하면 _par_을 호출하므로, 보통은 bound/filter/map 연산을 붙이기 위해서만 par을 명시적으로 호출하면 돼요.
병렬 배열은 실현/계산(배열에 대한 여러 연산 중 하나의 결과로 발생 — pvec/psort/pfilter-nils/pfilter-dupes) 전에 bounds, filters, 매핑 함수의 부착을 지원해요. 시퀀스로 보통 하듯 합성 연산을 단계별로 수행하는 대신, 맵과 필터는 대신 부착되고, 그리고 _par_에 ops를 제공함으로써 합성돼요. 부착에는 순서 민감성이 있다는 점에 주목하세요 — bounds가 filters보다, filters가 mappings보다 먼저 와요. 그러면 모든 연산은 배열이 실현될 때, 또는 preduce/pmin/pmax 같은 집계 연산을 수행할 때, 여러 스레드와 fork-join이 지원하는 정교한 작업 훔치기(work-stealing) 시스템을 사용해 병렬로 일어나요.
병렬 배열은 pvec을 사용해 Clojure 벡터로 실현될 수 있어요
(load-file "src/parallel.clj")
(refer 'parallel)
(def f (vec (take 20 (repeatedly #(rand-int 20)))))
f
-> [11 7 10 9 4 1 4 18 15 13 10 7 0 9 16 6 19 11 14 7]
;return value/index pairs of all entries < their index, in parallel
(pvec (par f :filter-index < :map-index vector))
-> [[1 5] [4 6] [7 11] [0 12] [9 13] [6 15] [11 17] [14 18] [7 19]]
반영 유틸리티 (clojure.reflect)
호스트 타입의 반영(reflection) 정보를 Clojure 데이터로 수집하고 구축하는 데 유용한 함수와 프로토콜을 제공해요.
REPL 유틸리티 (clojure.repl)
REPL에서 인터랙티브하게 사용하도록 의도된 유틸리티예요.
집합과 관계 대수 (clojure.set)
관계 대수(relational algebra)를 사용해 수학적 집합을 조작, 구축, 질의하는 데 유용한 함수예요.
문자열 처리 (clojure.string)
문자열을 조작하는 함수예요.
유닛 테스트 (clojure.test)
Clojure 유닛 테스트 프레임워크예요.
데이터 구조 순회 (clojure.walk)
중첩된 데이터 구조를 순회하고 조작하는 유틸리티예요.
XML (clojure.xml)
XML 데이터를 읽고 쓰는 유틸리티예요.
Zippers - 함수형 트리 편집 (clojure.zip)
Clojure는 지퍼(zipper)라 불리는 기법(네임스페이스 zip)을 사용한, 순수 함수형이며 일반적인 트리 순회와 편집을 포함해요. 배경에 대해서는 Huet의 논문을 참고하세요. 지퍼는 계층적 데이터 구조의 위치와, 그 위치에 도달하기 위해 거쳐 온 경로를 나타내는 데이터 구조예요. down/up/left/right 내비게이션과, 노드의 지역적 함수형 '편집', 삽입, 제거를 제공해요. 지퍼를 쓰면 트리를 통한 명령형이고 파괴적인 것처럼 보이는 코드를 쓸 수 있고, 끝나면 root를 호출해 모든 변경을 반영한 새 트리를 얻어요. 사실 아무것도 변경되지 않아요 — 전부 스레드 안전하고 공유 가능해요. next 함수는 깊이 우선 순회를 수행해서 이해하기 쉬운 루프를 만들게 해 줘요:
(def data '[[a * b] + [c * d]])
(def dz (zip/vector-zip data))
;find the second *
(-> dz zip/down zip/right zip/right zip/down zip/right zip/node)
-> *
;'remove' the first 2 terms
(-> dz zip/next zip/remove zip/next zip/remove zip/root)
-> [[c * d] +]
;'replace' * with /
(loop [loc dz]
(if (zip/end? loc)
(zip/root loc)
(recur
(zip/next
(if (= (zip/node loc) '*)
(zip/replace loc '/)
loc)))))
-> [[a / b] + [c / d]]
;'remove' *
(loop [loc dz]
(if (zip/end? loc)
(zip/root loc)
(recur
(zip/next
(if (= (zip/node loc) '*)
(zip/remove loc)
loc)))))
-> [[a b] + [c d]]
;original is intact
(zip/root dz)
-> [[a * b] + [c * d]]
지퍼 생성자는 중첩 seq, 중첩 벡터, 그리고 _xml/parse_가 생성한 xml 요소에 제공돼요. 다른 데이터 구조를 지원하는 데는 4-5줄 함수면 충분해요.