【发布时间】:2017-12-14 22:42:45
【问题描述】:
我正在使用函数规范,我想知道是否可以使用它来模拟编译类型检查? 宏是在编译时评估的,所以如果我可以这样做:
(:require [clojure.spec.alpha :as s]
[clojure.spec.test.alpha :as st])
(s/fdef divide
:args (s/cat :x integer? :y integer?)
:ret number?)
(defn divide [x y] (/ x y))
(st/instrument `divide)
(defmacro typed-divide [arg1 arg2]
(eval `(divide ~arg1 ~arg2)))
;; this should fail to compile?
(defn typed-divide-by-foo [arg]
(typed-divide arg :foo))
【问题讨论】:
-
仅供参考
(typed-divide arg 2)也会通过异常,因为符号arg是在编译时传入的。您只能使用typed-divide来划分其值在编译时已知的事物,这几乎仅限于文字。(typed-divide 2 :foo)应该会给你一个规范错误。 -
(eval 'x)和x一样,所以typed-divide的body可以简化为(divide ~arg1 ~arg2)。 -
可能是:
(defmacro typed-divide [arg1 arg2] (divide arg1 arg2))。但实际上只有在编译时知道两个参数时才会抛出:(defn typed-divide-by-foo [] (typed-divide 6 :foo))。尽管我对 clojure 的动态特性没有任何问题,但这是一项纯粹的学术调查:) -
哎呀,你说得对,不是
~。我假设您收到(typed-divide 6 :foo)的规范失败异常和(typed-divide arg :foo)的“无法解析符号”异常? -
查看:github.com/arohner/spectrum 它将准确捕获您在编译时遇到的错误。它仍处于早期 alpha 阶段,但比您提出的方案更好的长期解决方案。
标签: clojure macros clojure.spec