【问题标题】:Problem with Clojure Spec about simple parameter matchingClojure Spec 关于简单参数匹配的问题
【发布时间】:2021-08-04 11:31:38
【问题描述】:

我正在为 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)

我是新手,真的需要一些帮助才能继续前进。

谢谢。

【问题讨论】:

  • 与问题无关:将数字转化为关键字通常是不受欢迎的。只需使用数字作为键
  • @cfrick 我认为你是对的。感谢您分享您的想法。

标签: clojurescript clojure.spec


【解决方案1】:

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 标签而出错时,前者会提供更多上下文。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 2011-09-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2015-09-06
    相关资源
    最近更新 更多