我有一个带有宏的ns。im处理的令人讨厌的事情是,taoensso.timbre宏只作为一个可变表达式(timbre/info "a" "b" "c")工作。一个项目列表不会正确地记录(timbre/info ["a" "b" "c"])。我试图创建一个包装宏,它允许代码以相同的变量形式调用(logger/info),然后处理所有元素,然后传递到timbre/info
(ns logger
(:require [taoensso.timbre :as timbre :include-macros true])) ; a third party logger
;; A bit of pseudo code here. If you pass in a vector of args, you should get a vector of args with some changes
(defn scrub [args]
(if (listy)
(mapv (fn [a] (scrub args) args)
(if (is-entry a) {:a "xxx"} a)
(defmacro info
[& args]
`(timbre/info ~@(scrub args)))这是不起作用的,因为它会被立即调用,并且不会解析传入的符号。我需要像这两种都不起作用的东西。
(defmacro info
[& args]
`(timbre/info @(scrub-log-pii ~args)))
(defmacro info
[& args]
`(timbre/info ~@('scrub-log-pii args)))我的最后一个想法是尝试将音色宏包装成一个函数,这样宏和评估就会按正确的顺序进行。然而,没有办法“应用”到一个宏。
(defn info3
[& args]
(timbre/info (scrub-log-pii (vec args))))有什么想法吗?
发布于 2022-04-08 21:40:20
你遇到了一个使用宏的问题,这种宏被称为“海龟一路向下”。也就是说,不使用函数组合,您可能需要编写一个包装器宏,然后再编写另一个包装器宏,等等。
这个答案描述了编写宏的详细步骤:
对于你的具体问题,我们可以这样做:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[clojure.pprint :as pp]))
(defn infix-impl
[a op b]
(list op a b))
(defmacro infix
"Allows user to have Java-style infix operators:
(infix 2 + 3)
"
[a op b] (infix-impl a op b))
(defn infix-seq-impl
[args]
`(let [form# (cons 'infix ~args)
result# (eval form#)]
result#))
(defmacro infix-seq
[args] (infix-seq-impl args))
(dotest
(is= 5 (infix 2 + 3))
(let [params '[2 + 3]]
(pp/pprint (infix-seq-impl 'params))
(is= 5 (infix-seq params))))在这里,我们使用infix宏来演示如何创建一个包装宏infix-seq,该宏接受一个参数序列而不是N个标量参数。打印的输出显示生成的代码:
(clojure.core/let
[form__24889__auto__ (clojure.core/cons 'tst.demo.core/infix params)
result__24890__auto__ (clojure.core/eval form__24889__auto__)]
result__24890__auto__)--更通用的版本
下面的applied宏允许您传入要“应用”到param序列的宏的名称:
(defn applied-impl
[f args]
`(let [form# (cons ~f ~args)
result# (eval form#)]
result#))
(defmacro applied
[f args] (applied-impl f args))
(dotest
(nl)
(let [params '[2 + 3]]
; (applied 'infix params) ; using a single quote fails
(is= 5 (applied `infix params)) ; using a backquote works
(is= 5 (applied 'tst.demo.core/infix params)) ; can also use fully-qualified symbol with single-quote
(is= 5 (applied (quote tst.demo.core/infix) params)) ; single-quote is a "reader macro" for (quote ...)
))发布于 2022-04-09 07:57:03
对于这个问题(宏应用程序)的回答不是确切的,而是实用的timbre解决方案,它可能适用于您的具体情况:
这里 --您可以看到所有音色宏都使用log!宏,而后者又接受args的集合。
所以,只是将您的过程实现为
(defmacro info* [args] `(log! :info :p ~args ~{:?line (fline &form)}))应该能起作用。
https://stackoverflow.com/questions/71803261
复制相似问题