java Clojure While 循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1053926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:57:06  来源:igfitidea点击:

Clojure While Loop

javaclojureloopswhile-loop

提问by Hamza Yerlikaya

I trying clojure i am trying to figure out how to implement the following algorithm,

我在尝试 clojure 我想弄清楚如何实现以下算法,

I am reading from an input stream i want to continue reading until it is not a delimiter character.

我正在从输入流中读取我想继续读取直到它不是分隔符为止。

i can do this in java with a while loop but i can't seem to figure out how to do it in clojure?

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

while
   read
   readChar != delimiter

   do some processing....
end while

采纳答案by Nathan Shively-Sanders

I don't know Clojure, but it looks that, like Scheme, it supports "let loops":

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

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

Hope this is enough to get you started. I referred to http://clojure.org/special_forms#toc9to answer this question.

希望这足以让你开始。我参考了http://clojure.org/special_forms#toc9来回答这个问题。

NOTE: I know that Clojure discourages side-effects, so presumably you want to return something useful instead of '().

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

回答by wrongusername

Working on Clojure 1.3.0, and for what it's worth, you can write while loops in Clojure now by doing something akin to

在 Clojure 1.3.0 上工作,并且为了它的价值,您现在可以通过执行类似于以下操作的方式在 Clojure 中编写 while 循环

(while truth-expression
  (call-some-function))

回答by user499049

The loop approach will work fine in clojure however loop/recur are considered low level operations and higher order functions usually preferred.

循环方法在 clojure 中可以正常工作,但是循环/递归被认为是低级操作,通常更喜欢高阶函数。

Normally this sort of problem would be solved by creating a sequence of tokens (characters in your example) and applying on or more of clojure's sequence functions (doseq, dorun, take-while, etc.)

通常,这类问题可以通过创建一系列标记(您的示例中的字符)并应用一个或多个 clojure 的序列函数(doseq、dorun、take-while 等)来解决。

The following example reads the first username from /etc/passwd on unix like systems.

以下示例在类 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)))

回答by drewr

I came up with this in the spirit of line-seq. It's fully lazy and exhibits more of Clojure's functional nature than loop.

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

Full paste.

满贴

回答by jk.

A while-loop usually involves mutable variables, i.e. waiting until a variable meets a certain condition; in Clojure you'd usually use tail-recursion (which the compiler translates into a while-loop)

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

The following is not quite a solution, but this variation of the for-loop might be of help in some cases:

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

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

This will create a list of all the pairs of a and b until(< (* a b) 1000). That is it will stop as soon as the condition is met. If you replace :while with :when, they you can find allof the pairs that meet the condition, even after it finds one that doesn't.

这将创建一个包含所有 a 和 b 对的列表,直到(< (* a b) 1000)。也就是说,它会在满足条件后立即停止。如果您将 :while 替换为 :when,则它们可以找到所有满足条件的对,即使在找到不满足条件的对之后也是如此。

回答by Leonardo

I came out with this version:

我推出了这个版本:

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

It looks for a String, not a single char as delimiter!

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

Thanks!

谢谢!