Clojure core.typed注释适用于第三方宏

时间:2015-06-19 21:22:54

标签: clojure clojure-core.typed

我正在使用弹弓的throw+宏来引发一个类似的异常:

(throw+ {:type ::urlparse})

类型检查器不喜欢它:

Type Error (stream2es/http.clj:79:17) Bad arguments to apply:

Target:     [String t/Any * -> String]

Arguments:  (PersistentList String)
in: (clojure.core/apply clojure.core/format (clojure.core/list "throw+: %s" (clojure.core/pr-str %)))


Type Checker: Found 1 error

macro in slingshot看起来像:

(defmacro throw+
  ([object]
     `(throw+ ~object "throw+: %s" (pr-str ~'%)))
  ([object message]
     `(throw+ ~object "%s" ~message))
  ([object fmt arg & args]
     `(let [environment# (s/environment)
            ~'% ~object
            message# (apply format (list ~fmt ~arg ~@args))
            stack-trace# (s/stack-trace)]
        (s/throw-context ~'% message# stack-trace# environment#)))
  ([]
     `(s/rethrow)))

我在ann ^:no-checkapply上尝试过各种format表单但没有效果。因为它是一个宏,我假设我不能注释它,因为它取代了那里的代码。但我也不能像this other answer中建议的那样重写宏中的代码,因为它在库中。我如何逐步输入这种情况?

1 个答案:

答案 0 :(得分:1)

如果您无法重写throw+的实现,我建议使用这样的包装宏。

(defmacro typed-throw+ [object]
  `(let [o# ~object]
     (t/tc-ignore
       (throw+ o#))
     (throw (Exception.)))) ; unreachable
;; other arities are an exercise ..

这样,你仍然键入检查参数,core.typed仍然认为throw+总是抛出异常 - 它并不是真的知道这一点,但是最终的throw子句允许core.typed给出整个表达式类型Nothing

真正的答案应该是我们可以改进apply以了解应用非空列表将至少满足一个参数,但是这个答案今天应该有用。