1

特定のスキーマで名前が付けられたマップのキーのみを選択する関数を作成しました。

(ns foo.schema
  (:require [schema.core :as s]))

(defn select-schema
  "Given a schema and a map m, selects only the keys of m that are named in the schema."
  [m schema]
  (let [optional? #(instance? schema.core.OptionalKey %)
        wildcard? #(= s/Keyword %)]
    (if (some wildcard? (keys schema))
      m  ; the schema allows any keyword as a key, so just return the map
      (let [ks (->> schema keys (map #(if (optional? %) (:k %) %)))]
        (select-keys m ks)))))

これは、私の単体テストでは問題なく機能します。

(testing "Required key and wildcard"
    (let [schema {:foo s/Str, s/Keyword s/Any}]
      (is (= {:foo "Yup", :bar 42, :baz true} (select-schema {:foo "Yup", :bar 42, :baz true} schema)))
      (is (= {:foo "Yup", :bar 42} (select-schema {:foo "Yup", :bar 42} schema)))
      (is (= {:foo "Yup"} (select-schema {:foo "Yup"} schema)))))

ただし、foo.schema/select-schema完全に別のプロジェクトで使用すると (つまりlein install、私の foo プロジェクトで jar を構築し、それを私の中に貼り~/.m2/repository付けて、依存関係として名前を付けます)、次のようになりますClassNotFoundException

Exception in thread "main" java.lang.ExceptionInInitializerError, compiling:(insurrection/test/handler.clj:1:1)
    at clojure.lang.Compiler.load(Compiler.java:7142)
    ...
Caused by: java.lang.ExceptionInInitializerError
    at foo.schema__init.load(Unknown Source)
    at foo.schema__init.<clinit>(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    ...
Caused by: java.lang.ClassNotFoundException: schema.core.OptionalKey
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    ...

Prismatic Sc​​hema のソースを調べたところOptionalKey、defrecord タイプであることがわかりました。少しグーグルで調べてみると、 defrecord が Java クラスを生成し、それを定義する名前空間を要求した後にインポートする必要があることがわかりましたが、含むプロジェクトでそれを実行しようとしてfoo.schemaも違いはありません: 単体テストでは機能しますが、foo依存関係として使用する他のプロジェクトでは機能しません。

4

1 に答える 1