質問

私は、私は次のアルゴリズムを実装する方法を把握しようとしていますClojureのしようと、

私はそれが区切り文字でなくなるまで読み続けたい入力ストリームから読んでいます。

私は、whileループを使用してJavaでこれを行うことができますが、私はClojureの中でそれを行う方法を見つけ出すように見えることはできません?

while
   read
   readChar != delimiter

   do some processing....
end while
役に立ちましたか?

解決

私はClojureのを知りませんが、それはスキームのように、それは「聞かせてループ」をサポート、ということになります。

(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))

ループアプローチは、しかしながら、ループ/ RECUR Clojureのに正常に動作します低レベルの操作と考えられ、より高次の機能が通常好ましいです。

通常、この種の問題は、

(あなたの例では文字)を一連のトークンを作成し、Clojureののシーケンス機能(doseq、dorun、テイクしばらく、など)の以上に適用することによって解決されるだろう

次の例では、システムのような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の精神で、この思い付きました。それは完全に怠惰だとloopよりもClojureの機能の自然の多くを呈するます。

(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))))))))))

フル・ペーストするます。

A whileループは、通常、変数が特定の条件を満たすまで待機すなわち可変変数を含みます。 Clojureの中で、あなたは通常、末尾再帰を使用すると思います(コンパイラはwhileループに変換する)

次はかなり解決策ではなく、forループのこの変化は、いくつかのケースで助けになるかもしれません。

(for [a (range 100) 
      b (range 100) 
      :while (< (* a b) 1000)] 
    [a b]
  )

このは(< (* a b) 1000)までaとbののすべてのペアのリストを作成します。それはそれは、すぐに条件が満たされるように停止しますです。あなたは交換する場合:としながら、次の場合、彼らはあなたがそうでないものを発見した後も、条件を満たしているペアのすべて見つけることができます。

私は、このバージョンで出てきます:

(defn read-until
  [^java.io.Reader rdr ^String delim]
  (let [^java.lang.StringBuilder salida (StringBuilder.) ]
    (while
      (not (.endsWith (.toString salida) delim))
      (.append salida (str (char (.read rdr))))
    )
    (.toString salida)
  )
)

これは文字列ではなく、区切り文字として単一の文字を探します!

ありがとうございます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top