1
(require '[clojure.test.check.generators :as gen])

(def ACTIONS
  {:create-new-user #{}
   :edit-user #{:create-new-user}
   :create-new-board #{:create-new-user}
   :edit-board #{:create-new-board}
   :create-new-anonymous-comment #{:create-new-board}
   :create-new-signed-comment #{:create-new-board}
   :edit-comment-text #{:create-new-anonymous-comment :create-new-signed-comment}
   :edit-comment-text-and-flip-anonymity #{:create-new-anonymous-comment :create-new-signed-comment}
   :flip-anonymity #{:create-new-anonymous-comment :create-new-signed-comment}
   :vote-comment-up #{:create-new-anonymous-comment :create-new-signed-comment}
   :vote-comment-down #{:create-new-anonymous-comment :create-new-signed-comment}})

(def actions (-> ACTIONS keys vec gen/elements gen/vector))

(defn filter-actions-into-logical-order [as]
  (let [seen (atom #{})]
    (filter
     (fn [v]
       (let [required (get ACTIONS v)
             valid? (or (some? (some required @seen)) 
                        (and (empty? @seen) (= v :create-new-user)))]
         (when valid?
           (swap! seen conj v)
           true)))
     as)))

(def ordered-actions (gen/fmap #(-> % filter-actions-into-logical-order vec)  actions))

2 つのジェネレーターの例:

# (last (gen/sample actions 100))
[:edit-user :vote-comment-down :flip-anonymity :vote-comment-down :vote-comment-down :vote-comment-up :edit-user :create-new-anonymous-comment :edit-board :create-new-signed-comment :vote-comment-up :edit-comment-text-and-flip-anonymity :edit-user :create-new-signed-comment :edit-user :edit-user :vote-comment-down :edit-user :vote-comment-down :create-new-user :vote-comment-down :create-new-user :create-new-user :edit-comment-text-and-flip-anonymity :create-new-user :edit-comment-text-and-flip-anonymity :create-new-anonymous-comment :edit-comment-text :create-new-board :vote-comment-down :flip-anonymity :create-new-signed-comment :vote-comment-up :create-new-user :create-new-signed-comment :edit-user :create-new-user :create-new-board :vote-comment-down :create-new-board :create-new-board :create-new-board :edit-board :edit-comment-text-and-flip-anonymity :edit-user :edit-comment-text :create-new-signed-comment :vote-comment-up :edit-comment-text-and-flip-anonymity :flip-anonymity :create-new-anonymous-comment :create-new-anonymous-comment :edit-board :create-new-signed-comment :edit-comment-text-and-flip-anonymity :edit-board :vote-comment-up :edit-comment-text :create-new-board :edit-comment-text-and-flip-anonymity :create-new-board :vote-comment-down :edit-comment-text-and-flip-anonymity :vote-comment-up :create-new-user :vote-comment-up :edit-comment-text :edit-board :edit-comment-text-and-flip-anonymity :flip-anonymity :edit-board :create-new-anonymous-comment :flip-anonymity :create-new-signed-comment :edit-user :edit-comment-text-and-flip-anonymity :edit-comment-text :edit-comment-text :create-new-user :flip-anonymity :edit-user :vote-comment-up :edit-user :create-new-user :edit-comment-text :edit-comment-text :flip-anonymity :edit-comment-text :edit-board :flip-anonymity :edit-board :edit-comment-text :edit-user :create-new-user :flip-anonymity]


# (last (gen/sample ordered-actions 100))
[:create-new-user :edit-user :edit-user :create-new-board :edit-board :edit-user :create-new-anonymous-comment :edit-comment-text :edit-board :edit-user :edit-user :vote-comment-up :edit-comment-text :create-new-signed-comment :edit-comment-text :create-new-board :edit-comment-text :edit-comment-text :edit-comment-text :vote-comment-up :vote-comment-up :edit-board :edit-comment-text-and-flip-anonymity :create-new-signed-comment :create-new-anonymous-comment :create-new-signed-comment :edit-user :create-new-anonymous-comment :edit-board :create-new-board :create-new-anonymous-comment :create-new-board :flip-anonymity :create-new-anonymous-comment :edit-board :vote-comment-up :vote-comment-down :edit-board :edit-comment-text :edit-user :edit-comment-text :flip-anonymity :create-new-signed-comment :vote-comment-up :edit-comment-text-and-flip-anonymity :vote-comment-up :create-new-signed-comment :edit-comment-text :create-new-signed-comment :create-new-anonymous-comment :edit-board :create-new-anonymous-comment]

ACTIONSキーがアクションの名前で、値がそのアクションの (OR ベースの) 依存関係であるマップです。:create-new-user例として、何かを行う前にまず、する必要があります。:create-new-boardできるようにする前に:edit-board、少なくとも 1 つ必要です。:create-new-*-comment:edit-comment-text

上記のコードは機能しているように見えますが、醜いです。filter-actions-into-logical-order1)コードに特定の例外が必要な方法が好きではありません:create-new-user。2) 基本的にランダムなアクションのリストを取得し、アクションが順序付けされた意味を成すまでフィルタリングするのが好きではありません。

test.check を使用して、他の人がこのような一連のアクションをどのように生成するのか疑問に思っています。確かに、ジェネレーターのみを使用してそうする方法があるに違いありませんか?

4

2 に答える 2

2

を使用する再帰ジェネレーターを使用してこれを行うのはそれほど難しくありませんgen/bind(たとえば、最初にアクションのリストのサイズを生成し、次にそのサイズに対して再帰を使用してgen/bind、各ステップで以前に生成されたアクションを取得します)。このアプローチの大きな欠点はgen/bind、縮小ではうまく機能しないため、ほとんど縮小できない長い一連のアクションになる可能性が高いことです。

私は本当にこれのために何か良いものを考え出したい.

于 2015-12-29T02:02:33.863 に答える
1

まあ、filter-into-logical-order間違いなく、に切り替えることでよりクリーンになる可能性がありますreduce

(defn filter-into-logical-order [as]
  (last (reduce
         (fn [[seen accepted-as] action]
           (let[needed (get ACTIONS action)]
             (if (or (empty? needed) (some seen needed))
               [(conj seen action) (conj accepted-as action)]
               [seen accepted-as]))
           )
         [#{} []]
         as)))

しかし、それでも約 30% の空のベクトルが出力され、ジェネレーターではありません。ただし、文書化されたコンビネーターが実際にあなたが望むものをサポートしているかどうかはわかりません。gen/vectorvector-in-construction を内部ジェネレーターに渡すことをサポートしていないように見えるため、許可されている値を知ることができます。これは、要件が必要とする構造のようなものです。

于 2014-12-16T00:23:03.160 に答える