1

私の名前空間を正しくロードするこの関数があります:

(defn load-module [module-name]
    (use module-name)
)

そして、機能しない私の「同等の」マクロ:

(defmacro load-module-macro [module-name]
    `(
        (use '~module-name)
    )
)

問題がわかりません。

さらに、このマクロを使用して、構成で選択したモジュールをロードしたいと考えています。config.clj で、「save-data」関数を含むロガー モジュールの名前空間で var を定義します。次に、指定したロガーをコア プログラムにロードします。したがって、構成ファイルで直接使用するロガーを選択できます (ディスク上のロガー、データベース内のロガーなど)。それを行うための最良の方法はありますか?

編集 :

エラーメッセージ

IllegalArgumentException Don't know how to create ISeq from: java.lang.Character  clojure.lang.RT.seqFrom (RT.java:505)
4

2 に答える 2

3

いいえ、実際にはコード内で直接「使用」を使用したくありません。Use はそれが呼び出される名前空間全体を変更するため、ほとんど予測できない方法でコードが壊れる可能性があります。

代わりに、次のことを行う必要があります。ロギング インターフェイス (プロトコル) を実装し、config.clj で設定したものをキーワードとしてディスパッチする「メタ コンストラクター」を記述します。コード例

    (defprotocol ILog
      (save-data [this msg] "Logs message in msg."))



    (defn create-file-log
      "Returns an object implementing ILog, opens and flushes java.io.File file."
      [file]
      (let [f ... ;; create file writer here
            ]
        (reify ILog
          (save-data [this msg] ;; Write code that writes data to file here
            ))))

     ;; create other implementations like database here or elsewhere

     (defn create-log
       "Creates a log of of the type passed in type-kw."
       [type-kw]
       (case type-kw
         :file (create-file-log "./app-log.txt")
         ;; other types
         ))

これで、構成ファイルに設定されているキーワードを使用して create-log を呼び出すだけで、返されたオブジェクトをロギングを行う必要がある関数に渡すことができます。明らかに、グローバル オブジェクトとして定義することもできますが、それはお勧めしません。

最終的には、設定で目的のロギング方法のキーワード (type-kw) を設定するだけでなく、ファイル名やデータベース uri などの他のパラメーターも設定して、次のようなものを渡すことができるようにする必要があります。

   {:log-method :file
     :data {:fname "app-log.txt"}}
    or
   {:log-method :db
     :data {:uri "....

...この構造体を使用して reify コンストラクター create-file-log、create-db-log などのパラメーターを取得する create-log 関数に。

編集: switch ステートメントが気に入らないため、マルチメソッドでそれを行う方法は次のとおりです。

  (defmulti create-log :logging-method)
  (defmethod create-log :file
    [arg-map]
    (let [file (java.io.File. (:fname arg-map))]
      (if (.exists file)
        ... 

次に、config.cljにエントリを作成するだけです

  {...
   :log {:logging-method :file
         :fname "./log-file.txt"}}

新しいロギング タイプを作成するには、上記のような引数マップと create-log のコンストラクタ メソッドを想像するだけです。

于 2013-07-24T09:41:45.453 に答える