私はclojureを試しています。次のアルゴリズムを実装する方法を見つけようとしています.
区切り文字でなくなるまで読み続けたい入力ストリームから読み込んでいます。
while ループを使用して Java でこれを行うことができますが、clojure で行う方法がわかりませんか?
その間 読んだ readChar != 区切り文字 何とか加工して…… 終了する
私はclojureを試しています。次のアルゴリズムを実装する方法を見つけようとしています.
区切り文字でなくなるまで読み続けたい入力ストリームから読み込んでいます。
while ループを使用して Java でこれを行うことができますが、clojure で行う方法がわかりませんか?
その間 読んだ readChar != 区切り文字 何とか加工して…… 終了する
Clojure はわかりませんが、Scheme と同様に「let ループ」をサポートしているようです。
(loop [char (readChar)]
(if (= char delimiter)
'()
(do (some-processing)
(recur (readChar)))))
始めるにはこれで十分だと思います。この質問に答えるためにhttp://clojure.org/special_forms#toc9を参照しました。
注: Clojure が副作用を思いとどまらせることはわかっているので、おそらく '() の代わりに何か役に立つものを返したいと思うでしょう。
Clojure 1.3.0 に取り組んでいます。その価値はありますが、次のようなことを行うことで、Clojure で while ループを記述できるようになりました。
(while truth-expression
(call-some-function))
ループ アプローチは clojure で問題なく動作しますが、ループ/再帰は低レベルの操作と見なされ、通常はより高次の関数が優先されます。
通常、この種の問題は、一連のトークン (例の文字) を作成し、clojure のシーケンス関数 (doseq、dorun、take-while など) を適用することで解決されます。
次の例では、UNIX 系システムの /etc/passwd から最初のユーザー名を読み取ります。
(require '[clojure.java [io :as io]])
(defn char-seq
"create a lazy sequence of characters from an input stream"
[i-stream]
(map char
(take-while
(partial not= -1)
(repeatedly #(.read i-stream)))))
;; process the sequence one token at a time
;; with-open will automatically close the stream for us
(with-open [is (io/input-stream "/etc/passwd")]
(doseq [c (take-while (partial not= \:) (char-seq is))]
;; your processing is done here
(prn c)))
私はこれをの精神で思いついたline-seq
。それは完全に怠惰であり、Clojureの機能的性質の多くを示していますloop
。
(defn delim-seq
([#^java.io.Reader rdr #^Character delim]
(delim-seq rdr delim (StringBuilder.)))
([#^java.io.Reader rdr #^Character delim #^StringBuilder buf]
(lazy-seq
(let [ch (.read rdr)]
(when-not (= ch -1)
(if (= (char ch) delim)
(cons (str buf) (delim-seq rdr delim))
(delim-seq rdr delim (doto buf (.append (char ch))))))))))
while ループには通常、変更可能な変数が含まれます。つまり、変数が特定の条件を満たすまで待機します。Clojure では、通常、末尾再帰を使用します (コンパイラはこれを while ループに変換します)。
以下は完全な解決策ではありませんが、for ループのこのバリエーションが役立つ場合があります。
(for [a (range 100)
b (range 100)
:while (< (* a b) 1000)]
[a b]
)
これにより、まで の a と b のすべてのペアのリストが作成されます(< (* a b) 1000)
。つまり、条件が満たされるとすぐに停止します。:while を :when に置き換えると、条件に一致しないペアが見つかった後でも、条件に一致するすべてのペアを見つけることができます。