添加语法糖以使棱镜模式看起来像Core.Typed / Haskell

时间:2016-05-19 22:57:47

标签: haskell clojure clojurescript plumatic-schema clojure-core.typed

  1. 考虑core.typed注释函数的方式:

    (t/ann typed-function [t/Str :-> t/Str])
    
  2. 现在考虑Prismatic Sc​​hema注释函数的方式:

    (s/defn schema-function :- s/Str
           [arg :- s/Str]
           arg)
    
  3. 就我个人而言,我发现core.typed注释函数的方式更加清晰,更接近Haskell等强类型语言。

    问题:有没有办法在clojure中使用具有(2)效果但是(1)的视觉外观的棱镜模式制作某种宏或函数?也就是说,如下所示:'

    (custom-annotation-macro schema-function [s/Str :-> s/Str])
    (defn schema-function [arg] arg)
    

    这样效果仅仅是

    (s/defn schema-function :- s/Str
          [arg :- s/Str]
           arg)
    

1 个答案:

答案 0 :(得分:1)

说明如何使用两个宏来解决这个问题:

(def type-annots (atom (hash-map)))

(defn add-type-annot [fn-name ty]
  (swap! type-annots #(conj % [fn-name ty])))

(defmacro custom-annotation-macro [fn-name ty]
  (add-type-annot fn-name ty)
  nil)

(defn split-fun-type [ty]
  ;; You will need to write this one; 
  ;; it should split [a :-> b :-> c] to [[a b] c]
  ['[s/Str s/Int] 's/Str])

(defmacro defn-typed [fn-name args & body]
  (let [ty (get @type-annots fn-name)]
    (if ty
      (let [[arg-types ret-ty] (split-fun-type ty)
            args-typed (apply vector (apply concat (map vector args arg-types)))]
        `(s/defn ~fn-name :- ~ret-ty ~args-typed ~@body))
      `(defn ~fn-name ~args ~@body))))

我没有费心去实施split-fun-type,因为我真的不知道Clojure;以上是基于我的理解,它是一个Lisp。