Clojure:测试正在运行的属性的序列



>假设您要测试仅根据连续元素定义的属性的 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)) 可以测试广义斐波那契模式),我可以这样写:

(defn sequence-has-property? [f sequ n] (每?#(申请f%) (分区 n 1 个连续)))

问题:有没有更好(更快/更惯用)的方法?

自OP的链接问题:

只需使谓词函数本身接受可变参数,并让它进行分区/递归。你的单调?例如,核心中已经存在,称为<=

(<= 1 2 4 5)
=> true
(<= 1 2 1 5)
=> false

以下是 1、2 和可变参数版本的源代码:

(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)))

你可以做一个fib吗? 以同样的方式工作,让它接受可变参数并在三元组中重复:

(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

不,不知道 N 就没有办法做到这一点。你对sequence-has-property的所有定义对我来说都很好,没有重大改进。不过,在这种情况下,我会使用(partial apply f)而不是#(apply f %)。我没有明确的原因,因为在其他情况下,我更喜欢 lambda 而不是使用 partial - 我只是觉得这次看起来更好。

更简单的解决方案

(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

最新更新