gpt4 book ai didi

clojure - 更改 Clojure 中全局变量的值

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

我是 Clojure 的初学者,我遇到了一个问题,我什至不确定是否可以在 Closure 中完成。

所以问题如下。我已经实现了一个函数,可以从一个区间(直到极限)计算素数。

(defn gather_primes_in_range [range_start range_end target_number prime_list]
(if (or (= 0 target_number) (> range_start range_end) (= FIND_MORE_PRIMES false))
prime_list
(do
(if (is_prime? range_start)
(gather_primes_in_range (+ range_start 1) range_end (- target_number 1) (conj, prime_list, range_start))
(gather_primes_in_range (+ range_start 1) range_end target_number prime_list)
)
)
)
)

(defn find_nr_of_primes_in_range [range_start range_end target_number]
(if (< range_start 2)
(gather_primes_in_range 2 range_end target_number [])
(gather_primes_in_range range_start range_end target_number [])
)
)

这工作得很好。但我现在想要的是有一个全局变量,它应该存储在每个方法上,调用在变量中找到的素数以便稍后查找。在 Python、Ruby 或 Scala 等其他语言中,我只需使用一个 Set,在从函数返回之前向其中添加条目即可实现此目的。但在 Clojure 中我不知道如何解决这个问题。

基本上我尝试的是,在某个全局声明中:

(def PRIMES_FOUND_SO_FAR #{})

然后以某种方式在返回时将条目添加到该变量中。这在 Clojure 中是否可能?如果可以,如何实现?我尝试过使用 swap!atom 或 set! 来更改其他变量的值。但在任何情况下都无法让它在这里工作。

最佳答案

首先,我强烈建议您阅读 clojure 代码约定 What are Clojure's Naming Conventions?

让我向您展示代码的一些改进。

1) 应用 clojure 命名约定。

然后从(+变量1)切换到(inc变量)(与dec相同的优化)。

此外(= FIND_MORE_PRIMES false)可以简单地替换为find-more-primes?

最后,条件 (= 0 smthng) 可以用更惯用的方式编写 (zero? smthng)

现在您的代码看起来更具可读性:

(defn gather-primes-in-range [range-start range-end target-number prime-list]
(if (or (zero? target-number) (> range-start range-end) need-more-primes?)
prime-list
(do
(if (is-prime? range-start)
(gather-primes-in-range (inc range-start) range-end (dec target-number) (conj prime-list range-start))
(gather-primes-in-range (inc range-start) range-end target-number prime-list)))))

2) 现在我们应该删除多余的 do 调用,因为它包装了唯一的一个函数调用。

最后一个技巧是通过将整个 gather-primes-in-range 调用交换为 recur

来应用尾递归 ( http://clojure.org/special_forms#Special%20Forms--(recur%20exprs *))
(defn gather-primes-in-range 
[range-start range-end target-number prime-list]
(if (or (zero? target-number) (> range-start range-end) need-more-primes?)
prime-list
(if (is-prime? range-start)
(recur (inc range-start) range-end (dec target-number) (conj prime-list range-start))
(recur (inc range-start) range-end target-number prime-list))))

现在是回答你的问题的时候了。您不会从这种方法中受益

(def PRIMES_FOUND_SO_FAR #{})

因为您没有机会更改此设置。您可以处理的唯一一件事就是从该结构创建一些新的不可变数据结构。

正如@georgek提到的,你可以简单地使用 atom在这种特殊情况下。

(def PRIMES_FOUND_SO_FAR (atom #{}))

向原子添加新素数:

(swap! PRIMES_FOUND_SO_FAR conj prime-number)

用于提取值的 Deref 原子:

@PRIMES_FOUND_SO_FAR ;; or (deref PRIMES_FOUND_SO_FAR)
-> #{2 3 5 7 11}

无论如何,你的代码有点命令式,但你应该永远记住,clojure 是函数式语言,具有不可变的数据结构、函数作为参数等。使用全局变量根本不是好主意。顺便说一句,这就是你的函数在 clojure 风格中的样子:

(defn gather-primes-in-range [start end target-number]
(take target-number (filter is-prime? (range start end))))

关于clojure - 更改 Clojure 中全局变量的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14790917/

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