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. 它是完全惰性的,并且比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 回答
0

我出来了这个版本:

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

它寻找一个字符串,而不是单个字符作为分隔符!

谢谢!

于 2015-06-03T18:37:55.143 回答