键入的Clojure错误

时间:2014-08-02 19:06:01

标签: clojure clojure-core.typed

我在我的项目中实施core.typed注释。以下代码工作正常:

(require ['clojure.core.typed :as 't])

(t/ann foo [String String -> String])
(defn foo [x y]
  (str x y))

(t/ann works [String String -> String])
(defn works [x y]
  (t/let [z :- (t/Vec String), (shuffle [x y])
          a :- String, (nth z 0)
          b :- String, (nth z 1)]
    (foo a b)))

如果我稍微改变了函数定义,我会遇到几个不同的错误:

(t/ann fails-1 [String String -> String])
(defn fails-1 [x y]
  (t/let [z :- (t/Vec String), (shuffle [x y])
          ; Fails because (t/Vec String) is not included
          ; in the domain of first or second
          a :- String, (first z)
          b :- String, (second z)]
    (foo a b)))

(t/ann fails-2 [String String -> String])
(defn fails-2 [x y]
  (t/let [[a b] :- (t/Vec String), (shuffle [x y])]
    ; Fails because a and b are of type (t/U nil String)
    (foo a b)))

从类型的角度来看,我原本预计这三个例子或多或少是等价的。具体来说,我假设:

  • (t/Vec String)将位于nthfirst
  • 的范围内
  • (shuffle [x y])nil类型为x
  • 时,y的范围不包括String

这是core.typed的限制,还是我有一个根本的误解?

1 个答案:

答案 0 :(得分:1)

现在要理解的主要内容是nth,以及具体如何使用nth进行解析。

nth type

(∀ [x y]
   (λ [(∪ (∩ Sequential (Seqable x)) (Indexed x)) AnyInteger → x]
      [(∪ nil (∩ Sequential (Seqable x)) (Indexed x)) AnyInteger y → (∪ x y)]
      [(∪ nil (∩ Sequential (Seqable x)) (Indexed x)) AnyInteger → (∪ nil x)]))

如果没有默认值nth,如果在其边界之外传递集合和索引,则会抛出异常。键入的Clojure不会尝试阻止此异常。

(t/cf (t/fn [a :- (t/ASeq t/Int)] :- t/Int (nth a 0)))
;=> [(t/IFn [(t/ASeq t/Int) -> (t/U Integer Long BigInt BigInteger Short Byte)]) {:then tt, :else ff}]

使用默认值时,默认值始终是结果类型的一部分。

(t/cf (t/fn [a :- (t/ASeq t/Int)] :- (t/U nil t/Int) (nth a 0 nil)))
=> [(t/IFn [(t/ASeq t/Int) -> (t/U nil Integer Long BigInt BigInteger Short Byte)]) {:then tt, :else ff}]

向量解构扩展为nth,默认值为nil。

另请注意,shuffle的返回类型没有长度信息。有时,异构数据结构的解构比同类数据结构更准确。