0

with-open と clojure.java.io/reader を使用して txt ファイルからデータを解析する関数を作成し、データを処理するためにリーダー関数を複数回呼び出す別の関数を作成したとします。

(defn grabDataFromFile [file patternString]   
     (let [data (atom [])]
        (with-open [rdr (clojure.java.io/reader file)] 
         (doseq [line (line-seq rdr)] 
           (if  (re-matches  (re-pattern  patternString) line) (swap! data conj line))))
        @data))


(defn myCalculation [file ]
  (let [data1 (grabDataFromFile file "pattern1")
        data2 (grabDataFromFile file "pattern2")
        data3 (grabDataFromFile file "pattern3")]
    ;calculations or processes of data1, data2, data3....))

私の質問は、この myCalculation 関数内で、基になるコードが clojure リーダーでファイルを 1 回だけ開き、必要なすべてのデータを 1 回で取得するのに十分スマートであるかということです。それとも、関数grabDataFromFileの呼び出し回数と同じ回数ファイルを開いたり閉じたりしますか? (この例では 3)

フォローアップの質問は、リーダーが十分に賢くない場合、および「パーサー」コードと「処理」コードを意図的に分離する必要がある場合、速度を上げるために何ができるでしょうか?

4

1 に答える 1

2

grabDataFromFile呼び出されるたびに、(終了時に) リーダーを開いたり閉じたりします。基礎となるコードは、関数が明示的に提供された情報なしで呼び出し元のコンテキストを検出できるほどスマートにすることはできません。

各行grabDataFromFileで動作するパーサーロジックである別の関数を受け入れるようにします(または、各行で実行したい任意の関数である可能性があります)

(defn grabDataFromFile [file patternString process-fn]   
  (with-open [rdr (clojure.java.io/reader file)] 
    (doseq [line (line-seq rdr)] 
      (process-fn line))))




(defn myCalculation [file]
  (let [patterns [["pattern1" (atom [])]
                  ["pattern2" (atom [])]
                  ["pattern3" (atom [])]]
        pattern-fns (map (fn [[p data]]
                           (fn [line]
                             (if  (re-matches (re-pattern  p) line)                              
                               (swap! data conj line)))) patterns)
        pattern-fn (apply juxt pattern-fns)]
    (grabDataFromFile file pattern-fn)
    ;perform calc on patterns atoms
    ))
于 2013-03-22T06:44:58.140 に答える