2017-06-25 6 views
2

Hier ist meine clojure Spezifikation für Schluckauf wie Syntax geschrieben.clojure spec fdef nicht funktioniert - während rekursive Definition übergeben

(:require 
    [clojure.spec.alpha :as s] 
    [clojure.spec.test.alpha :as st] 
    )) 


(s/def ::tag (s/and 
       keyword? 
       #(re-matches #":[a-z]+([0-9]+)?" 
          (str %)))) 

(s/def ::org-content (s/cat 
         :tag ::tag 
         :content (s/+ (s/or 
            :str string? 
            :content ::org-content 
            )))) 

ich eine einfache Funktion spec hier geschrieben -

(s/fdef org-headers-h3 
     :args (s/cat :contact ::org-content) 
     :ret keyword?) 

(defn org-headers-h3 [doc] 
    (first doc)) 

(st/instrument `org-headers-h3) 

(org-headers-h3 [:div [:h1 "d"]]) 

Es führt die folgenden Fehler -

*Call to #'modcss2.parser/org-headers-h3 did not conform to spec: 
    In: [0] val: [:div [:h1 "d"]] fails spec: :modcss2.parser/tag at: 
    [:args :contact :tag] predicate: keyword? :clojure.spec.alpha/spec 
    #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x6613f384 
    "[email protected]"] 
    :clojure.spec.alpha/value ([:div [:h1 "d"]]) 
    :clojure.spec.alpha/args ([:div [:h1 "d"]]) 
    :clojure.spec.alpha/failure :instrument* 

ich mich scheinen, erhalte ich Fehler für falsche Art von Argumente übergeben . aber ich werde für die folgende Aussage wahr.

(s/valid? ::org-content [:div [:h1 "d"]]) => true 

Antwort

2

Ein s/cat in einer anderen nicht verschachtelt sie bedeutet, sie verketten gerade. Dies gilt für alle Regex-Spezifikationen.

(s/conform (s/cat :foo (s/cat :bar int?)) [1]) ;=> {:foo {:bar 1}} 

(s/conform (s/cat :foo (s/cat :bar int?)) [[1]]) ;=> ::s/invalid 

Ihre :args spec erweitert, um so etwas wie: (s/cat :contact (s/cat :tag ::tag ,,,))

So verschachteln sie können Sie s/spec verwenden.

(s/conform (s/cat :foo (s/spec (s/cat :bar int?))) [[1]]) ;=> {:foo {:bar 1}} 

Alle Regex-Spezifikationen verketten sich so. In diesem Fall ist es sinnvoll, s/and zu verwenden, um zu überprüfen, ob es sich um einen Vektor handelt, und ihn zu einer Nicht-Regex-Spezifikation zu machen, damit er normal verschachtelt wird.

(s/conform (s/cat :foo (s/and vector? (s/cat :bar int?))) [[1]]) ;=> {:foo {:bar 1}} 

Also, Ihr Problem zu beheben:

(s/def ::org-content 
    (s/and vector? 
     (s/cat 
      :tag ::tag 
      :content (s/+ (s/or 
         :str string? 
         :content ::org-content))))) 
Verwandte Themen