gpt4 book ai didi

macros - 如何向类 defn 的 Clojure 宏添加文档字符串支持?

转载 作者:行者123 更新时间:2023-12-02 09:36:51 24 4
gpt4 key购买 nike

我编写了一个宏来将函数定义包装在一些有用的日志记录中:

(defmacro defn-logged
"Wraps functions in logging of input and output"
[fn-name args & body]
`(defn ~fn-name ~args
(log/info '~fn-name "input:" ~@args)
(let [return# (do ~@body)]
(log/info '~fn-name "output:" return#)
return#)))

这对于没有文档字符串的函数非常有效:

(defn-logged foo
[x]
(* 2 x))

(foo 3)
; INFO - foo input: 3
; INFO - foo output: 6
; 6

但是如果使用文档字符串的函数严重失败:

(defn-logged bar
"bar doubles its input"
[x]
(* 2 x))
; IllegalArgumentException Parameter declaration clojure.tools.logging/info should be a vector

如何让我的宏同时适用于有和没有文档字符串的函数?

最佳答案

一种方法是查看传递给 defn-logged 的参数。如果名称后的第一个是字符串,则将其用作 doc 字符串,否则将 doc 留空:

(defmacro defn-logged
"Wraps functions in logging of input and output"
[fn-name & stuff]
(let [has-doc (string? (first stuff))
doc-string (if has-doc (first stuff))
[args & body] (if has-doc (rest stuff) stuff)]
`(defn ~fn-name {:doc ~doc-string} ~args
(println '~fn-name "input:" ~@args)
(let [return# (do ~@body)]
(println '~fn-name "output:" return#)
return#))))

用文档字符串测试:

(defn-logged my-plus "My plus documented" [x y] (+ x y))

(doc my-plus)
; -------------------------
; user/my-plus
; ([x y])
; My plus documented
; nil

(my-plus 2 3)
; my-plus input: 2 3
; my-plus output: 5
; 5

没有文档字符串的测试:

(defn-logged my-mult [x y] (* x y))

(doc my-mult)
; -------------------------
; user/my-mult
; ([x y])
; nil
; nil

(my-plus 2 3)
; my-mult input: 2 3
; my-mult output: 6
; 6

它仍然不是 defn 的完全等价物,至少因为 defn 支持在映射、阅读器宏和字符串中传递的元数据。但它适用于文档字符串。

关于macros - 如何向类 defn 的 Clojure 宏添加文档字符串支持?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24897818/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com