2017-07-03 4 views
1

私は機能のマップを定義します。clojureを持つフォルダにすべてのソースファイルを動的に含めるにはどうすればよいですか?

(ns fs 
    (:require [folder/a :as a] 
      [folder/b :as b] 
      [folder/c :as c]) 

(def functions {:a a/f :b b/f :c c/f}) 

(doseq [[_ f] functions] (f)) 

は今、私はフォルダ内の多くの名前空間を追加したい、と私は上記のコードを変更する必要はありません。 functionsには、フォルダ内の各名前空間のfをどのようにして動的に取り込むことができますか。

+1

この質問は表現が難しく、混乱します。答えが必要な場合は、(1)あなたが望むもの、(2)あなたが試したもの、(3)結果が何かを明確にする必要があります。 –

+0

あなたの質問は私には不明な点がありますが、https://github.com/ztellman/potemkin#import-varsとhttps://github.com/marick/suchwow/blob/master/test/で確認できます。 such/f_immigration.clj – nha

答えて

1

まず、いくつかのヘルパー:

(defn directory 
    "Get directory from path" 
    [path] 
    (clojure.java.io/file path)) 

(defn file-names 
    "Get file names of the files in the directory." 
    [files] 
    (map (fn [file] (.getName file)) files)) 

(defn namespace 
    "Remove the extension from the file name and prefix with folder-name" 
    [folder-name file-name] 
    (->> (clojure.string/split file-name #"\.") 
     (butlast) 
     (apply str) 
     (str folder-name ".") 
     (symbol))) 

は、その後、あなたのフォルダからすべての名前空間を取得するには、パスとフォルダ名が必要です。

(def namespaces 
    (let [names (->> "/path/to/your/folder-name" 
        directory 
        file-seq ;; Gets the tree structure of the directory 
        rest ;; Get rid of the the directory name 
        file-names)] 
    (map (partial namespace "folder-name") names))) 

次のns-publicsを経由して、すべての名前空間のパブリック関数を取得します:

(def functions 
    (->> namespaces 
     (map (juxt keyword (comp vals ns-publics))) 
     (into {}))) 

;; => prints {:namespace-key '(fn-a fn-b) :namespace-key2 '(fn-b fn-c)} 

これは、すべてのpubli cは名前空間キーの後の名前空間内で機能します。

次のように私たちは、機能を実行することができます。もちろん

(doseq [[_ ns-fns] functions 
     f ns-fns] (f)) 

を、ゼロのアリティを持つ関数については、この唯一の作品は。それ以外の場合は、引数をfに渡す必要があります。

関連する問題