gpt4 book ai didi

clojure - 为什么 Clojure 不支持宏中的私有(private)函数?

转载 作者:太空宇宙 更新时间:2023-11-03 18:40:06 25 4
gpt4 key购买 nike

我在尝试实现 xor 宏时遇到了问题。

我无法在宏中使用 private 函数。

例子如下:

私有(private)函数

(defn :^private xor-result
[x y]
(if (and x y)
false
(or x y)))

(defmacro xor
([] true)
([x] x)
([x & next]
`(let [first# ~x
second# ~(first next)]
(if (= (count '~next) 1)
(xor-result first# second#)
(xor (xor-result first# second#) ~@(rest next))))))

这是错误:

CompilerException java.lang.IllegalStateException: var: #'kezban.core/xor-result is not public

当我删除 ^:private 标志时,问题解决了

问题是:这种行为的原因是什么?


更新:我可以通过以下方法使用私有(private)函数

私有(private)函数

(defn ^:private xor-result
[x y]
(if (and x y)
false
(or x y)))

新宏

(defmacro xor
([] true)
([x] x)
([x & next]
(let [first x
second `(first '(~@next))
result (xor-result (eval first) (eval second))]
`(if (= (count '~next) 1)
~result
(xor ~result ~@(rest next))))))

最佳答案

如果你在 ns1 中有一个宏:

(ns ns1)

(defn- my-fun [x] (first x))

(defmacro my-macro [x] (my-fun ~x))

并在另一个命名空间中使用它:

(ns ns2
(:require [ns1 :refer [my-macro]]))

(my-macro [1 2])

编译器会在编译阶段调用这个宏,在ns2命名空间中生成代码,变成:

(ns ns2
(:require [ns1 :refer [my-macro]]))

(ns1/my-fun [1 2])

并且这段代码最终会被编译成字节码。

如您所见,编译器将在 ns2 命名空间中看到 ns1 的私有(private)函数的使用,并会对其进行投诉。

要调试您的宏,您可以使用 macroexpand查看应用宏的结果。

您还需要记住,您的宏对您的程序数据起作用:代表您的代码的数据结构(符号、列表、向量等)。例如,在您的宏的第二个版本中,它按原样处理符号,而不是绑定(bind)到它们的运行时值:

(macroexpand '(xor true false))
;; => (if (clojure.core/= (clojure.core/count (quote (false))) 1) true (boot.user/xor true))

(macroexpand '(xor (zero? 1) (zero? 0)))
;; => (if (clojure.core/= (clojure.core/count (quote ((zero? 0)))) 1) false (boot.user/xor false))

如您所见,您的 xor-result 函数不会使用实际的运行时值来调用,而是使用代表您的代码的数据来调用。 xor-result 在编译期间直接在您的宏中调用。在宏的第一个版本中,它在宏生成的代码内部使用,在编译期间不被调用。

关于clojure - 为什么 Clojure 不支持宏中的私有(private)函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39656535/

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