Добавление синтаксического сахара, чтобы сделать призматическую схему похожей на Core.Typed/Haskell

  1. Рассмотрим путь core.typed аннотирует функцию:

    (t/ann typed-function [t/Str :-> t/Str])
    
  2. Теперь рассмотрим способ, которым призматическая схема аннотирует функцию:

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

Лично я нахожу способ, которым core.typed функция аннотации должна быть более понятной и ближе по духу к типизированным языкам, таким как Haskell.

Вопрос: Есть ли способ создать какой-то макрос или функцию в замыкании с помощью Призматической схемы, которая имеет эффект (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 ответ

Чтобы проиллюстрировать, как вы можете решить эту проблему с помощью двух макросов:

(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; вышеизложенное основано на моем понимании того, что это Лисп.

Другие вопросы по тегам