假设您要为仅根据连续元素定义的属性测试Clojure序列。例如,单调性。
(defn monotonic?
[sequence]
(every? #(<= (first %) (second %))
(partition 2 1 sequence)))
但实际上我想为许多不同的属性做这件事。我可以为每个复制这个,或者我可以抽象:
(defn sequence-has-property?
[f sequ]
(every? #(apply f %)
(partition 2 1 sequ)))
如果我想抽象出测试所依赖的先前术语的数量(例如,以便#(=%3(+ %% 2))可以测试广义的Fibonacci模式),我可以写:
(defn sequence-has-property? [f sequ n] (每个?#(申请f%) (分区n 1 sequ)))
问题:是否有更好的(更快/更惯用)方式?
答案 0 :(得分:2)
取自OP的相关问题:
只需使谓词函数本身采用可变参数,并让它进行分区/重复。你的单调?例如,已经存在于核心中,并被称为<=
(<= 1 2 4 5)
=> true
(<= 1 2 1 5)
=> false
这里是1,2和可变参数arg版本的来源:
(source <=)
(defn <=
"Returns non-nil if nums are in monotonically non-decreasing order,
otherwise false."
{:inline (fn [x y] `(. clojure.lang.Numbers (lte ~x ~y)))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (. clojure.lang.Numbers (lte x y)))
([x y & more]
(if (<= x y)
(if (next more)
(recur y (first more) (next more))
(<= y (first more)))
false)))
你可以制造一个?以同样的方式工作,让它采用可变参数并重复三元组:
(defn fib?
[a b & [c & r]]
(if (= c (+ a b))
(if r
(recur b c r)
true)
false))
(fib? 0 1 1)
=> true
(fib? 2 3 5 8 13)
=> true
答案 1 :(得分:1)
不,如果不知道N,就无法做到。所有sequence-has-property
的定义对我来说都很好,没有重大改进。不过,我在这种情况下使用(partial apply f)
而不是#(apply f %)
。我没有明确的原因,因为在其他情况下我更喜欢lambda使用partial
- 我觉得这次看起来更好。
答案 2 :(得分:0)
更简单的解决方案
(defn monotonic? [a-seq]
(or (apply <= a-seq) (apply >= a-seq)
)
)
(monotonic? [1 2 3]) => true
(monotonic? [0 1 10 11]) => true
(monotonic? [1 2 1 0]) => false