Clojure While Loop

时间:2009-06-28 00:29:19

标签: java clojure loops while-loop

我尝试使用clojure,我试图弄清楚如何实现以下算法,

我正在读取输入流,我想继续阅读,直到它不是分隔符。

我可以在带有while循环的java中执行此操作,但我似乎无法弄清楚如何在clojure中执行此操作?

while
   read
   readChar != delimiter

   do some processing....
end while

6 个答案:

答案 0 :(得分:10)

我不知道Clojure,但它看起来像Scheme一样支持“let loops”:

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

希望这足以让你入门。我提到http://clojure.org/special_forms#toc9来回答这个问题。

注意:我知道Clojure不鼓励副作用,所以大概你想要返回一些有用的东西而不是'()。

答案 1 :(得分:5)

使用Clojure 1.3.0,并且为了它的价值,你现在可以通过做类似于

的事情在Clojure中编写while循环
(while truth-expression
  (call-some-function))

答案 2 :(得分:3)

循环方法在clojure中可以正常工作,但是loop / recur被认为是低级操作,而高阶函数通常是首选。

通常情况下,这类问题可以通过创建一系列令牌(示例中的字符)并应用一个或多个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)))

答案 3 :(得分:2)

我本着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))))))))))

Full paste

答案 4 :(得分:1)

while循环通常涉及可变变量,即等到变量满足某个条件;在Clojure中,你通常使用尾递归(编译器将其转换为while循环)

以下不是一个解决方案,但在某些情况下,for循环的这种变化可能会有所帮助:

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

这将创建一个包含a和b 的所有对的列表,直到 (< (* a b) 1000)。也就是说,只要满足条件,它就会停止。如果你替换:while with:when,你可以找到满足条件的所有对,即使它找到了不符合条件的对。

答案 5 :(得分:0)

我推出了这个版本:

getBoundingClientRect()

它查找String,而不是单个char作为分隔符!

谢谢!