最短的 Clojure 静态类型

shortest Clojure static typing

对 clojure 函数进行类型检查的最简单、最短的方法是什么。常规的 ann 形式很短:

(ann bar [Number -> Number])
(defn bar [b]
  (+ 2 (foo b)))

但是我们能不能(用宏之类的)让它看起来更小,比如:

(defn bar [b : Number -> Number]
  (+ 2 (foo b)))

感谢您的建议!

我觉得Plumatic Schema is the best. See also this blog post.

这是一个例子:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require [schema.core :as s]))

(s/defn add2 :- s/Num ; "superclass" for any number
  [a :- s/Int ; must be an integer type
   b :- Double] ; Must be a java.lang.Double
  (+ a b))

(dotest
  (throws? (add2 1 2))
  (throws? (add2 1.0 2))
  (is= 3.0 (add2 1 2.0)))

I also have some predefined "types" 除了基本的。例如,tupelo.schema/Keymap 是任何带有关键字键的映射。 Pair 是任何长度为 2 的向量或序列,等等


更新

另请参阅 my Clojure template project。特别是, 文件 test/clj/_bootstrap.clj 存在的唯一目的是在您键入 lein test 时启用 Plumatic Sc​​hema 类型检查(默认情况下它们被禁用,因此在生产中没有成本)。

严格来说,这是规范检查而不是静态类型,但您可能需要检查 Guardrails (a fork of Ghostwheel,它是未维护的)旨在解决静态类型确实存在的一些问题以及更多问题:

(>defn ranged-rand
   [start end]
   [int? int? | #(< start end)
    => int? | #(>= % start) #(< % end)]
   (+ start (long (rand (- end start)))))