Clojure循环集合

时间:2017-12-14 10:58:53

标签: clojure

我想知道这是否是循环收集的正确方法:

(def citrus-list ["lemon" "orange" "grapefruit"])

(defn display-citrus [citruses]
  (loop [[citrus & citruses] citruses]
    (println citrus)
    (if citrus (recur citruses))
    ))

(display-citrus citrus-list)

我有三个问题:

  1. 最终的打印显示为零,是否可以或者如何避免它?
  2. 我明白什么&在这个例子中正在做,但在其他情况下我没有看到它,也许你可以提供一些例子
  3. 获得相同结果的任何其他示例?
  4. 谢谢, R上。

3 个答案:

答案 0 :(得分:2)

首先,您的实施是错误的。如果您的列表包含nil

,则会失败
user> (display-citrus [nil "asd" "fgh"])
;;=> nil
nil

如果列表为空,则打印不需要的nil:

user> (display-citrus [])
;;=> nil
nil

你可以这样修理:

(defn display-citrus [citruses]
  (when (seq citruses)
    (loop [[citrus & citruses] citruses]
      (println citrus)
      (if (seq citruses) (recur citruses)))))

1)完全没问题:对于非空集合,函数内的最后一个调用是println,返回nil,而对于空集合,你不会调用任何东西,这意味着{将返回{1}}(clojure函数始终返回值)。为了避免在你的情况下为零,你应该显式返回一些值(例如这样):

nil

2)有些关于destructuring的文章可以帮助你

3)是的,有一些方法可以做到这一点。最简单的是:

(defn display-citrus [citruses] (when (seq citruses) (loop [[citrus & citruses] citruses] (println citrus) (if (seq citruses) (recur citruses)))) citruses) user> (display-citrus citrus-list) ;;=> lemon ;;=> orange ;;=> grapefruit ["lemon" "orange" "grapefruit"]

答案 1 :(得分:2)

回答上一个问题,你应该避免在Clojure中使用loop。这种形式适用于真正了解自己所做工作的有经验的用户。在您的情况下,您可以使用更加用户友好的表单doseq。例如:

(doseq [item collection]
  (println item))

您也可以使用map,但请记住,它会返回一个新的列表(如果您的情况为nil s),这有时是不可取的。比如说,您只对打印感兴趣,但不对结果感兴趣。

此外,map是懒惰的,在使用doall打印或评估之前,我们不会对其进行评估。

答案 2 :(得分:1)

出于大多数目的,您可以使用mapforloop

=> (map count citrus-list)
(5 6 10)

=> (for [c citrus-list] (count c))
(5 6 10)

=> (loop [[c & citrus] citrus-list
           counts []]
     (if-not c counts
       (recur citrus (conj counts (count c)))))
[5 6 10]

我倾向于尽可能多地使用map。语法更简洁,它清楚地将控制流(顺序循环)与转换逻辑分开(计算值)。

例如,只需将map替换为pmap

,即可并行运行相同的操作(计数)
=> (pmap count citrus-list)
[5 6 10]

在Clojure中,most operations on collection are lazy。只要您的程序不需要新值,它们就不会生效。要立即应用效果,可以将循环操作括在doall

=> (doall (map count citrus-list))
(5 6 10)

如果您不关心返回值,也可以使用doseq。例如,您可以将doseqprintln一起使用,因为该函数将始终返回nil

=> (doseq [c citrus-list] (println c))
lemon
orange
grapefruit