11

私はclojureを試しています。次のアルゴリズムを実装する方法を見つけようとしています.

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

while ループを使用して Java でこれを行うことができますが、clojure で行う方法がわかりませんか?

その間
   読んだ
   readChar != 区切り文字

   何とか加工して……
終了する
4

6 に答える 6

10

Clojure はわかりませんが、Scheme と同様に「let ループ」をサポートしているようです。

(loop [char (readChar)]
   (if (= char delimiter)
       '()
       (do (some-processing)
           (recur (readChar)))))

始めるにはこれで十分だと思います。この質問に答えるためにhttp://clojure.org/special_forms#toc9を参照しました。

注: Clojure が副作用を思いとどまらせることはわかっているので、おそらく '() の代わりに何か役に立つものを返したいと思うでしょう。

于 2009-06-28T01:01:44.843 に答える
5

Clojure 1.3.0 に取り組んでいます。その価値はありますが、次のようなことを行うことで、Clojure で while ループを記述できるようになりました。

(while truth-expression
  (call-some-function))
于 2011-12-26T06:14:12.107 に答える
3

ループ アプローチは 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)))
于 2011-12-27T00:28:13.757 に答える
2

私はこれをの精神で思いついた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))))))))))

フルペースト

于 2009-06-28T21:11:53.013 に答える
1

while ループには通常、変更可能な変数が含まれます。つまり、変数が特定の条件を満たすまで待機します。Clojure では、通常、末尾再帰を使用します (コンパイラはこれを while ループに変換します)。

以下は完全な解決策ではありませんが、for ループのこのバリエーションが役立つ場合があります。

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

これにより、まで の a と b のすべてのペアのリストが作成されます(< (* a b) 1000)。つまり、条件が満たされるとすぐに停止します。:while を :when に置き換えると、条件に一致しないペアが見つかった後でも、条件に一致するすべてのペアを見つけることができます。

于 2011-02-18T16:37:26.390 に答える