看看下面的函数。我想传递一个因子向量并测试向量中的任何元素是否是x
. 我怎么做?
(defn multiple?
"Takes a seq of factors, and returns true if x is multiple of any factor."
([x & factors] (for [e m] ))
([x factor] (= 0 (rem x factor))))
看看下面的函数。我想传递一个因子向量并测试向量中的任何元素是否是x
. 我怎么做?
(defn multiple?
"Takes a seq of factors, and returns true if x is multiple of any factor."
([x & factors] (for [e m] ))
([x factor] (= 0 (rem x factor))))
(defn multiple? [x & factors]
(some zero? (map #(rem x %) factors)))
如果所有测试都失败,也会some
返回nil
,如果你需要它实际返回false
,你可以放一个true?
:
(defn multiple? [x & factors]
(true? (some zero? (map #(rem x %) factors))))
请注意,some
短路并且map
是惰性的,因此multiple?
一旦找到匹配项就停止。例如,以下代码针对序列进行测试1,2,3,4,...
。
=> (apply multiple? 10 (map inc (range)))
true
multiple?
显然,如果不对序列中的每个数字进行测试,这种计算只能终止。
您只能使用some
.
=> (defn multiple? [x factors]
(some #(zero? (rem x %)) factors))
#'user/multiple?
=> (= true (multiple? 10 [3 4]))
false
=> (= true (multiple? 10 [3 4 5 6]))
true
some
将停止在第一个因素。
试试这个,使用显式尾递归:
(defn multiple? [x factors]
"if any of the elements in the vector is a factor of x"
(loop [factors factors]
(cond (empty? factors) false
(zero? (rem x (first factors))) true
:else (recur (rest factors)))))
上述解决方案的优点包括:一旦发现向量中的任何元素是否是 的因子,它就会立即停止x
,而无需遍历整个向量;由于使用尾递归,它高效且在恒定空间中运行;它直接返回一个布尔结果,不需要考虑返回的情况nil
。像这样使用它:
(multiple? 10 [3 4])
=> false
(multiple? 10 [3 4 5 6])
=> true
如果您想避免显式传递向量的需要(用于调用这样的过程:)(multiple? 10 3 4 5 6)
)然后只需将 a 添加&
到参数列表中,就像它在问题中一样。
一种更符合 Clojurian的方法是编写一个更通用的函数:它不会回答真/假问题,而是返回x
. 而且因为序列是惰性的,如果你想知道它是否为空,它几乎同样有效。
(defn factors [x & fs]
(for [f fs :when (zero? (rem x f))] f))
(factors 5 2 3 4)
=> ()
(factors 6 2 3 4)
=> (2 3)
那么你可以通过简单地使用来回答你原来的问题empty?
:
(empty? (factors 5 2 3 4))
=> true
(empty? (factors 6 2 3 4))
=> false