JVM에 부과 된 크기 제한 때문에 이처럼 큰 데이터를 컴파일 된 코드에 포함하지 못할 수도 있습니다. 특히 한 가지 방법으로 64 KiB를 초과 할 수 없습니다. 아래에 더 자세히 설명하는 방식으로 데이터를 임베드하려면 클래스 파일에 많은 양의 데이터가 포함될 필요가 있습니다. 좋은 생각 같지는 않습니다.
당신이 데이터 구조를 사용하고있는 점을 감안 읽기 전용, 당신은 다음, 그 파일을 포함 (즉, edn에 대한 Clojure의 문자 표기법에 따라 직렬화 형식의)를 .clj
/.edn
로 방출, 한 번을 구성 할 수 있습니다 클래스 경로에 "리소스"로 포함되어 있으므로 überjar에 포함됩니다 (기본값 Leiningen 설정을 사용하는 resources/
) :uberjar-exclusions
에 의해 제외되지 않는 한 überjar에 포함되어 project.clj
에있는 런타임에 리소스에서 읽습니다. Clojure 독자의 전속력 :
(ns foo.core
(:require [clojure.java.io :as io]))
(defn get-the-huge-data-structure []
(let [r (io/resource "huge.edn")
rdr (java.io.PushbackReader. (io/reader r))]
(read r)))
;; if you then do something like this:
(def ds (get-the-huge-data-structure))
;; your app will load the data as soon as this namespace is required;
;; for your :main namespace, this means as soon as the app starts;
;; note that if you use AOT compilation, it'll also be loaded at
;; compile time
당신은 또한 그것을 überja에 추가 할 수 없습니다 r을 사용하는 대신 앱을 실행할 때 classpath에 추가하십시오. 이렇게하면 überjar 자체가 거대하지 않아도됩니다.
지속적인 Clojure 데이터 이외의 처리 print-method
(직렬화 할 때) 및 리더 태그 (비 직렬화 할 때)를 사용하여 수행 할 수 있습니다. Arthur는 이미 리더 태그를 사용하여 시연했습니다. print-method
를 사용하여, 당신은 당신 만 직렬화 할 때 정의 된 print-method
방법이 필요
물론
(defmethod print-method clojure.lang.Ref [x writer]
(.write writer "#ref ")
(print-method @x writer))
;; from the REPL, after doing the above:
user=> (pr-str {:foo (ref 1)})
"{:foo #ref 1}"
뭔가를 할 것; deserialize 코드는 혼자 남겨 둘 수 있지만 적절한 데이터 판독기가 필요합니다. 데이터 구조는 기본적으로 Clojure의 (Clojure의 영속 콜렉션에 의해 처리 불변의 데이터가 포함 된 가정
임의로 중첩 플러스 :
내가 흥미있는 문제를 내장 데이터를 발견하면, 잠시 동안의 코드 크기 문제를 무시하고 같은 숫자, 문자열 (이 목적을 위해 원자), 키워드, 기호로 원자 항목, 더 참고 문헌 등), 당신은 실제로 당신의 코드에 포함 할 수 없습니다 :
이
(defmacro embed [x]
x)
생성 된 바이트 코드는 다음과 x
를 다시합니다 클래스 파일에 포함 된 상수와 clojure.lang.RT
클래스의 정적 메서드를 사용하여 모든 것을 읽습니다. RT.vector
및 RT.map
).
위의 매크로는 아무 것도 없기 때문에 이것은 물론 리터럴을 컴파일하는 방법입니다. 우리는 비록 일을 더 재미있게 만들 수 있습니다
(ns embed-test.core
(:require [clojure.java.io :as io])
(:gen-class))
(defmacro embed-resource [r]
(let [r (io/resource r)
rdr (java.io.PushbackReader. (io/reader r))]
(read r)))
(defn -main [& args]
(println (embed-resource "foo.edn")))
이 컴파일시에 foo.edn
를 읽고 (클래스 파일의 데이터를 재구성하기 위해 적절한 상수 및 코드 등의 의미에서) 컴파일 된 코드의 결과를 포함합니다. 런타임에는 더 이상의 판독이 수행되지 않습니다.
읽기 전용 구조로되어 있다면,'ref's를 완전히 피할 것을 제안합니다. 액세스가 느려지고 직렬화가 더 까다로워 질뿐만 아니라 전체 구조가 더 많은 메모리를 사용하게됩니다. 불변 영구 데이터 구조는 여러분의 친구입니다. – mikera