Clojure:测试运行属性的序列

时间:2014-03-30 04:50:58

标签: 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))可以测试广义的Fibonacci模式),我可以写:

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

问题:是否有更好的(更快/更惯用)方式?

3 个答案:

答案 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