代码之家  ›  专栏  ›  技术社区  ›  ericky

使用clojure规范检查cons上的类型一致性?

  •  1
  • ericky  · 技术社区  · 7 年前

    如果我和借书人一起经营图书馆:

    (s/def ::brs (s/coll-of ::br/borrower))
    (s/def ::bks (s/coll-of ::bk/book))
    

    我想要一个将一个项添加到集合中的通用函数:

    (defn add-item [x xs]
      (if (some #{x} xs)
        xs
        (cons x xs)))
    

    如何编写一个规范来确保我不能向借款人添加图书,反之亦然?

    因为这个规范:

    (s/fdef add-item
        :args (s/fspec :args (s/or :is-brs (s/and (s/cat :x ::br/borrower) (s/cat :xs ::brs))
                                   :is-bks (s/and (s/cat :x ::bk/book) (s/cat :xs ::bks))))
        :ret (s/or :ret-brs ::brs
                   :ret-bks ::bks))
    

    不工作。:

    谢谢你的帮助!

    1 回复  |  直到 7 年前
        1
  •  2
  •   Taylor Wood    7 年前

    使用int/string定义 ::brs ::bks :

    (s/def ::brs (s/coll-of int?))
    (s/def ::bks (s/coll-of string?))
    

    这应该有效:

    (s/fdef add-item
            :args (s/or
                    :brs (s/cat :x int? :xs ::brs)
                    :bks (s/cat :x string? :xs ::bks))
            :ret (s/or :brs ::brs
                       :bks ::bks))
    ;; instrument function here
    (add-item 1 [2])
    => (1 2)
    (add-item "1" [2]) ;; throws exception