2014-03-30 32 views
2

假設您想要測試僅根據連續元素定義的屬性的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序列具有屬性 並[f色曲N] (每#(申請F%) (分段N 1 sequ)))

問題:有沒有更好的(更快/更習慣)的方式?

+0

難道你不再感興趣的是依賴於兩個以上的連續元素屬性? – Thumbnail

+0

哦,我是。我不是故意編輯出來的。 – galdre

回答

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

不,沒有辦法不知道N.你所有的定義sequence-has-property看起來不錯,我沒有重大的改進。不過,在這種情況下,我會使用(partial apply f)而不是#(apply f %)。我沒有明確的理由,因爲在其他情況下,我更喜歡lambda使用partial - 我只是覺得這次看起來更好。

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