Why does Clojure support private functions in a macro?

I tried to implement the xor macro and came up with a problem.

I could not use the private function in the macro.

Here is an example:

private function

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

Macro

(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))))))

Here is the Error :

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

The problem resolves when I remove the ^: private flag .

Question: What is the reason for this behavior?


The UPDATE . I can use a private function with the following approach .

private function

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

new macro

(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))))))
+4
source share
1 answer

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])

.

, ns1 ns2 .

, macroexpand, .

, : datastructures, (, , ..). , , :

(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 . , , .

+5

Source: https://habr.com/ru/post/1655589/


All Articles