我是新来的clojure,并且在创建宏观上遇到一些麻烦。
Clojure中的代码评估了前1000,000个整数的总和:
(apply + (range 1E6))
此基准代码评估总和,但也打印了该代码所采用的纳秒数的数量:
(let [start (System/nanoTime)
result (apply + (range 1E6))]
end (System/nanoTime)]
(println "Took:" (- end start) "ns")
result)
我将如何在以下形式会议上创建宏观。(基准Expr)的值是对Expr的评估,它打印了评估纳秒中Expr所需的时间?
(defmacro benchmark [code]
...)
另外,我对宏一般的工作方式有些困惑。为什么我们不能以以下形式使用普通函数?
(defn benchmark [code]
...)
在您的情况下,宏和普通功能之间的主要区别在于参数评估顺序。传递给功能的参数将在传递给功能体之前进行评估,而宏观参数则传递给宏观主体(这意味着宏观主体都会看到您输入的代码形式并可以在纯代码上操作)。小示例:
user>
(defn add2 [a]
(println "a is" a)
(+ a 2))
#'user/add2
user> (add2 (+ 10 10))
a is 20
22
user>
(defmacro add2-m [a]
(println "a is" a)
`(+ ~a 2))
#'user/add2-m
user> (add2-m (+ 10 10))
a is (+ 10 10)
22
这意味着构成记录的函数将是毫无意义的,因为在第一个时间戳之前将对基准的代码作为ARG进行评估。
。,您所需的宏可能看起来像:
(defmacro bm [form]
`(let [start# (System/nanoTime)
result# ~form
end# (System/nanoTime)]
(println "Took:" (- end# start#) "ns")
result#))
在编译时扩展到以下内容:
;;(bm (apply + (range 1E6)))
;;=> Took: 131009572 ns
;;=> 499999500000
(let*
[start__6355__auto__
(. java.lang.System nanoTime)
result__6356__auto__
(apply + (range 1000000.0))
end__6357__auto__
(. java.lang.System nanoTime)]
(println "Took:" (- end__6357__auto__ start__6355__auto__) "ns")
result__6356__auto__)
这是一个非常好的网站,可以了解单引号以及如何正确使用它们https://8thlight.com/blog/colin-jones/2012/05/22/quoting-without-confusion.html
作为附带说明