Clojure Spec 关于简单参数匹配的问题
Problem with Clojure Spec about simple parameter matching
我正在为 Clojure(script) 规范苦苦挣扎。
稍微查了一下是什么地方出问题了,但是解决不了
(defn filter-ids
[[items fields] _]
(let [ids
(for [item items
field-tags (vals fields)
:let [item-tags (-> item second :tags)
item-id (first item)]
:when (and
(seq field-tags)
(empty? (set/difference field-tags item-tags)))]
item-id)]
(into #{} ids)))
以上代码是我试图定义规范的。 (fdef)
我定义了规范
(spec/def :common/id (spec/and
keyword?
#(-> %1 name js/parseInt nat-int?)))
(spec/def :common/label string?)
(spec/def :common/tags (spec/coll-of string? :kind set?))
(spec/def :common/item (spec/keys :req-un [:common/label :common/tags]))
(spec/fdef filter-ids
:args (spec/cat
:useful (spec/cat
:items (spec/map-of :common/id :common/item)
:fields (spec/map-of :common/id :common/tags))
:useless any?)
:ret (spec/coll-of :common/id :kind set?))
而当我运行用仪器时,出现错误。
(stest/instrument `filter-ids)
(filter-ids [{:0 {:label "task0" :tags #{"one" "two"}}}
{:0 #{"three"}, :1 #{"one"}}]
nil)
; Execution error - invalid arguments to taggy.states.subs/filter-ids at (<cljs repl>:1).
[{:0 {:label "task0", :tags #{"two" "one"}}} {:0 #{"three"}, :1 #{"one"}}] - failed: map? at: [:useful :items]
似乎规范认为第一个参数需要是地图,这不是我想要的。
当我在下方点赞时,它不会抱怨地图?。 (虽然仍然是一个错误,因为它根本无效)
(filter-ids {{:0 {:label "task0" :tags #{"one" "two"}}} 1
{:0 #{"three"}, :1 #{"one"}} 2}
nil)
我是新手,真的需要一些帮助才能继续前进。
谢谢。
spec/cat
是一个“序列正则表达式”,如果将它嵌套在另一个 spec/cat
.
中,它会“展开”
您可以将内部 spec/cat
调用包装在 spec/spec
调用中,以防止展开,或者您可以切换到 spec/tuple
(并删除 :items
和 :fields
个标签):
(spec/fdef filter-ids
:args (spec/cat
:useful (spec/spec (spec/cat
:items (spec/map-of :common/id :common/item)
:fields (spec/map-of :common/id :common/tags)))
:useless any?)
:ret (spec/coll-of :common/id :kind set?))
;; or
(spec/fdef filter-ids
:args (spec/cat
:useful (spec/tuple
(spec/map-of :common/id :common/item)
(spec/map-of :common/id :common/tags))
:useless any?)
:ret (spec/coll-of :common/id :kind set?))
这两个都可以。您选择哪一个可能取决于您在错误消息中想要的信息(我认为前者会在您出错时提供更多上下文,因为 :items
和 :fields
标签)。
我正在为 Clojure(script) 规范苦苦挣扎。 稍微查了一下是什么地方出问题了,但是解决不了
(defn filter-ids
[[items fields] _]
(let [ids
(for [item items
field-tags (vals fields)
:let [item-tags (-> item second :tags)
item-id (first item)]
:when (and
(seq field-tags)
(empty? (set/difference field-tags item-tags)))]
item-id)]
(into #{} ids)))
以上代码是我试图定义规范的。 (fdef)
我定义了规范
(spec/def :common/id (spec/and
keyword?
#(-> %1 name js/parseInt nat-int?)))
(spec/def :common/label string?)
(spec/def :common/tags (spec/coll-of string? :kind set?))
(spec/def :common/item (spec/keys :req-un [:common/label :common/tags]))
(spec/fdef filter-ids
:args (spec/cat
:useful (spec/cat
:items (spec/map-of :common/id :common/item)
:fields (spec/map-of :common/id :common/tags))
:useless any?)
:ret (spec/coll-of :common/id :kind set?))
而当我运行用仪器时,出现错误。
(stest/instrument `filter-ids)
(filter-ids [{:0 {:label "task0" :tags #{"one" "two"}}}
{:0 #{"three"}, :1 #{"one"}}]
nil)
; Execution error - invalid arguments to taggy.states.subs/filter-ids at (<cljs repl>:1).
[{:0 {:label "task0", :tags #{"two" "one"}}} {:0 #{"three"}, :1 #{"one"}}] - failed: map? at: [:useful :items]
似乎规范认为第一个参数需要是地图,这不是我想要的。
当我在下方点赞时,它不会抱怨地图?。 (虽然仍然是一个错误,因为它根本无效)
(filter-ids {{:0 {:label "task0" :tags #{"one" "two"}}} 1
{:0 #{"three"}, :1 #{"one"}} 2}
nil)
我是新手,真的需要一些帮助才能继续前进。
谢谢。
spec/cat
是一个“序列正则表达式”,如果将它嵌套在另一个 spec/cat
.
您可以将内部 spec/cat
调用包装在 spec/spec
调用中,以防止展开,或者您可以切换到 spec/tuple
(并删除 :items
和 :fields
个标签):
(spec/fdef filter-ids
:args (spec/cat
:useful (spec/spec (spec/cat
:items (spec/map-of :common/id :common/item)
:fields (spec/map-of :common/id :common/tags)))
:useless any?)
:ret (spec/coll-of :common/id :kind set?))
;; or
(spec/fdef filter-ids
:args (spec/cat
:useful (spec/tuple
(spec/map-of :common/id :common/item)
(spec/map-of :common/id :common/tags))
:useless any?)
:ret (spec/coll-of :common/id :kind set?))
这两个都可以。您选择哪一个可能取决于您在错误消息中想要的信息(我认为前者会在您出错时提供更多上下文,因为 :items
和 :fields
标签)。