2017-10-05 3 views
1

:ここカスタムclojure.specジェネレータを作成するにはどうすればよいですか?私は接続と呼ばれる次のようなデータ構造を仕様にしようとしている

{:id "some string" :channel "instance of org.httpkit.server.AsyncChannel" }

は私のスペックです:

(defn make-channel [] 
    (proxy [AsyncChannel] [nil nil] 
    (toString [] "mock AsyncChannel"))) 

(defn channel-gen 
    [] 
    (->> (s/gen (s/int-in 0 1)) 
     (gen/fmap (fn [_] (make-channel))))) 

(s/def ::channel (s/spec (::channel-type) 
         :gen channel-gen)) 

(s/def ::id string?) 

(s/def ::connection (s/keys :req-un [::channel ::id])) 

(s/fdef make-connection 
     :args ::channel 
     :ret ::connection) 

私は次のエラーを取得していると私が何であるか見当もつかないここで間違っている:

clojure.lang.ExceptionInfo: Unable to construct gen at: [] for: [email protected] 
clojure.lang.Compiler$CompilerException: clojure.lang.ExceptionInfo: Unable to construct gen at: [] for: [email protected] #:clojure.spec.alpha{:path [], :form #object[gameserve.ws$make_connection 0x788ffa19 "[email protected]"], :failure :no-gen} 

答えて

3

私はあなたのエラーを再現するが、mは物事のカップルを指摘したかったことができませんこの作業を手伝ってください。

あなたのgen/fmapのパラメータを無視することは、すでに事物です:gen/returnです。

ここで引数なしのキーワードを呼び出すと、IllegalArgumentExceptionがスローされます。 ::channel-type周りの括弧を削除するだけです。

(s/def ::channel (s/spec (::channel-type) 
         :gen channel-gen)) 

ここでは、1つのことについて話すargs仕様を作成しています。 :argsは常に引数のシーケンスです。関数が引数を1つしか取らない場合は、長さが1のシーケンスです。通常はs/catを使用します。

(s/fdef make-connection 
    :args ::channel 
    :ret ::connection) 

次のように動作します。 (チャンネルの内容が正しいとみなします)

(ns foo.core 
    (:require 
    [clojure.spec.gen.alpha :as gen] 
    [clojure.spec.alpha :as s])) 

(defn make-channel [] 
    :mock-channel) 

(defn channel-gen 
    [] 
    (gen/return (make-channel))) 

(s/def ::channel-type any?) 

(s/def ::channel (s/spec ::channel-type 
         :gen channel-gen)) 

(s/def ::id string?) 

(s/def ::connection (s/keys :req-un [::channel ::id])) 

(defn make-connection [c]) 

(s/fdef make-connection 
    :args (s/cat :c ::channel) 
    :ret ::connection) 

(comment 

    (s/exercise ::connection) 
    ;;=> ([{:channel :mock-channel, :id ""} {:channel :mock-channel, :id ""}] 
    ;; [{:channel :mock-channel, :id "k"} {:channel :mock-channel, :id "k"}] ,,,) 

    (s/exercise-fn `make-connection) 
    ;;=> ([(:mock-channel) nil] [(:mock-channel) nil] ,,,) 

) 
+0

ありがとうございます。確かにこのコードは動作していますが、私は自分のコードでREPLのためにいくつかのゴミを捨てていることに気づきました。私は本当にREPLのもののために(コメント...)を使用する習慣に入る必要があります。手伝ってくれてありがとう。 –

+0

clojure.specを使用している現実のプロジェクトをお勧めできますか?私はClojureには新しく、実際にこのことを学ぶのに役立ちます。 –

+2

ライブラリに関する限り、[clojure.java.jdbc](https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc/spec.clj)があります。 。私は実際に完全に焼いたアプリケーションについては分かりませんが、他の人が共有したい例があるかもしれません。 – madstap

関連する問題