gpt4 book ai didi

variables - 用于函数重置的 clojure

转载 作者:行者123 更新时间:2023-12-01 08:23:03 24 4
gpt4 key购买 nike

我正在尝试解决 4clojure.com 上的问题我应该在不使用 count 的情况下计算集合中元素的数量。我尝试了两种使用 forlet 的方法,我认为它们应该可以工作,但似乎 for 循环一直在重置 let

(#(for [x %  :let [y 0]] (inc y)) [1 2 3 4 5])
;; which returns
(1 1 1 1 1)

(#(let [y 0] (for [x %] (inc y))) [1 2 3 4 5])
;; which returns
(1 1 1 1 1)

所以我的问题是为什么会发生这种情况,以及如何让我的“变量”为集合中的每个项目保持递增。只是说变量这个词就让我想知道我是否正在尝试制作一些不能可变的东西,但我仍然觉得这应该可行。

最佳答案

在这两种情况下,您都不能更改 y 的值:

在第一种情况下,for 在每个循环步骤中重新引入 y,这就是为什么你不能改变它的值,即使它是可变的。

第二种情况表明该值是真正不可变的,每一步都为您提供 (inc y),但 y 始终为零。简单例子:

(let [x 10]
(inc x)
x)

;;=> 10

一般来说,这类任务通常可以通过以下方法解决:

第一个是简单的递归:

(defn count-rec [data]
(if (seq data)
(inc (count-rec (rest data)))
0))

user> (count-rec [1 2 3 4 5])
;;=> 5

它在某种程度上是有缺陷的,因为它不是尾递归的,并且对于大型集合会失败

第二个是clojure的loop:

(defn count-loop [data]
(loop [res 0 data data]
(if (seq data)
(recur (inc res) (rest data))
res)))

user> (count-loop [1 2 3 4 5])
;;=> 5

您也可以使用非常相似的显式尾递归:

(defn count-tailrec
([data] (count-tailrec 0 data))
([c data] (if (seq data)
(recur (inc c) (rest data))
c)))

user> (count-tailrec [1 2 3 4 5])
;;=> 5

第三个将使用 reduce 函数:

(defn count-reduce [data]
(reduce (fn [res _] (inc res)) 0 data))

user> (count-reduce [1 2 3 4 5])
;;=> 5

只是为了好玩,你也可以使用这种方式(我不建议这样做,因为与 reduce 相比它是一种过度杀伤):

(defn count-map [data]
(apply + (map (constantly 1) data)))

user> (count-map [1 2 3 4 5])
;;=> 5

您也可以使用 clojure 的可变原语,但它不是惯用的,应尽可能避免使用:

(defn count-atom [data]
(let [c (atom 0)]
(run! (fn [_] (swap! c inc)) data)
@c))

user> (count-atom [1 2 3 4 5])
;;=> 5

作弊来了[剧透警告!]

4clojure 在这个任务中阻塞了 count 函数的使用,但不阻塞 java 集合的 .size 方法,所以可以用#(.size (seq %))

关于variables - 用于函数重置的 clojure,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47923102/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com