【问题标题】:Clojure core.typed annotation for apply inside a 3rd-party macroClojure core.typed 注释,用于在 3rd-party 宏中应用
【发布时间】:2015-06-20 13:40:19
【问题描述】:

我正在使用 slingshot 的 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)))

我在applyformat 上尝试了各种ann ^:no-check 表单,但没有一个有效。由于它是一个宏,我假设我不能注释它,因为它替换了那里的代码。但我也无法像this other answer 中建议的那样重写宏中的代码,因为它在库中。在这种情况下如何逐渐输入?

【问题讨论】:

    标签: clojure clojure-core.typed


    【解决方案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 以了解应用非空列表将满足至少一个参数,但是这个答案今天应该可以工作。

    【讨论】:

    • 在最近重读文档时完全掩盖了tc-ignore!包装宏效果很好,可以调味。知道人们已经为这样的通用代码贡献了包装器的任何库吗?
    • 很遗憾没有。有clojure.core.typed.async
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    相关资源
    最近更新 更多