【问题标题】:Clojure loop reads one extraClojure 循环多读一个
【发布时间】:2010-11-06 13:00:42
【问题描述】:

当长度为 4 时,以下循环执行 5 次。从流中读取 5 个字符。


(loop [i (.read stream)  result ""  counter length]
    (let [c (char i)]
      (println "=>" c)
      (if (zero? counter)
        result
        (recur (.read stream) (str result c) (dec counter)))))

【问题讨论】:

    标签: loops clojure stream lisp


    【解决方案1】:

    您应该在执行read 之前测试zero?。请注意,即使以 length == 0 开头,您的版本也会调用一次 read

    (loop [result "" counter length]
      (if (zero? counter)
        result
        (let [c (char (.read stream))]
          (println "=>" c )
          (recur (str result c) (dec counter)))))
    

    另一种避免显式loop的方式:

    (apply str 
           (take length 
                 (repeatedly #(let [c (char (.read stream))]
                                (println "=>" c) c)))))
    

    【讨论】:

    • 所以我应该在循环之前添加另一个测试为零,但我仍然不明白为什么它运行了 5 次?这是 clojure 行为还是我错过了什么?
    • 您的版本在 counter = 4, 3, 2, 1, 0 时进行读取。这是五次迭代。第一次读取是在循环绑定向量内完成的,最初设置i,接下来的四次读取是通过recur 完成的。当您测试counterzero? 时,您已经阅读了太多内容。我发布的版本将读取移动到 if 语句中,从而避免了这个问题。你不需要在循环之前进行其他测试。
    • 在你的脑海中逐步循环,你会看到第 5 个字符来自哪里。基本上,在循环中的两个地方重复相同的事情(.read 流)是一种代码味道。
    【解决方案2】:

    我不知道 clojure,但在我看来你正在以“结果”形式再次阅读流,这就像 CL 中的 final 吗?

    【讨论】:

      猜你喜欢
      • 2012-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多