简体   繁体   English

clojure中的函数定义宏

[英]function definition macro in clojure

I'm trying to make a macro that transform this: 我正在尝试制作一个可以改变它的宏:

(defn-check my-checked-function
  check-function
  [a A
   b B]
  (do-something a b))

into: 成:

(defn my-checked-function [a b]
  {:pre [(= (check-function a) A) 
         (= (check-function b) B)]}
  (do-something a b))

I'm new to clojure, could anyone show me how to do that? 我是clojure的新手,有人能告诉我该怎么做吗?

(defmacro defn-check [name check-fn args & tail]
  (let [docstring (if (string? (first tail)) (first tail))
        tail (if docstring (next tail) tail)
        params (take-nth 2 args)
        checks (take-nth 2 (next args))
        cf (gensym "cf__")]
    `(let [~cf ~check-fn]
       (defn ~name
         ~@(if docstring [docstring])
          ~(vec params)
         {:pre ~(mapv (fn [p c]
                        `(= (~cf ~p) ~c))
                      params
                      checks)}
         ~@tail))))

This allows you to specify a docstring if you'd like, but not an attribute map (see (doc defn) ; adding support for that would be straightforward). 这允许您根据需要指定文档字符串,但不允许指定属性映射(请参阅(doc defn) ;添加(doc defn)支持将非常简单)。

Example: 例:

user> (defn-check funky-add odd? [x true y false] "foo" (+ x y))
#'user/funky-add
user> (doc funky-add)
-------------------------
user/funky-add
([x y])
  foo
nil
user> (funky-add 1 2)
3
user> (funky-add 2 1)
AssertionError Assert failed: (clojure.core/= (cf__2268 x) true)  user/eval2269/funky-add--2270 (form-init1446120099766722611.clj:1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM