在clojure中做倒计时功能的更好方法是什么?

时间:2016-03-01 21:17:01

标签: clojure

在制作更复杂的功能时,我想做类似下面的代码。然而,对于简单的倒计时而言似乎有点过于复杂。特别是需要在函数和循环中使用次数。有更好/更简单的方法吗?答案/建议表示赞赏。

(defn the-final-countdown
  [times]
  (loop [times times]
    (if (> times 0)
      (do (print times) (recur (dec times)))
      (print times))))

(the-final-countdown 7);;OUTPUT -> 76543210

据我所知,Reduce在这种情况下不起作用,因为函数接受的是值而不是列表。

2 个答案:

答案 0 :(得分:3)

编写纯函数而不是使用副作用几乎总是一个好主意。

你在这里做的是通过小于或等于times的所有非负整数(以相反的顺序)并打印每个整数。一种更简单的方法是使用内置的range函数生成这些整数的序列,然后使用str将该序列的所有元素连接成一个字符串:

(defn the-final-countdown [times]
  (apply str (range times -1 -1)))

示例:

(the-final-countdown 7)
;=> "76543210"

如果您确实需要在控制台上打印某些内容,只需拨打the-final-countdown然后打印结果:

(print (the-final-countdown 7))
;   76543210
;=> nil

如果您愿意,您还可以通过生成增加的序列并在其上调用-1来避免功能定义中那些丑陋的reverse

(defn the-final-countdown [times]
  (apply str (reverse (range (inc times)))))

请注意,reverse需要实现range返回的整个延迟序列才能完成其工作,但由于我们无论如何都要转换为字符串,因此不会真的很重要。

如果您要打印非常长的数字列表,但将整个序列保留在内存中可能不太可行。在这种情况下,可能需要在函数中使用副作用,使用run!可以实现:

(defn the-final-countdown [times]
  (run! print (range times -1 -1)))

答案 1 :(得分:2)

这是实现此目的的一种方法:

user=> (defn countdown [n] (dotimes [x n] (println (- n x))))
#'user/countdown
user=> (countdown 7)
7
6
5
4
3
2
1
nil