在同一个clojure宏中定义和解析

时间:2018-09-27 09:51:24

标签: clojure macros

我想实现在最近定义了符号本身的宏中返回名称空间解析符号:

(ns my-namespace)

(defmacro def&resolve [a b]
  `(do
     (def ~a 12)
     (def ~b ~(resolve a))))

(def&resolve foo bar)
bar ;=> nil

在示例bar中返回nil。但是,我希望它返回my-namespace.foo。我知道这是行不通的,因为在调用resolve时,尚未定义a。但是,对于我的用例[1],我需要a在宏扩展时进行名称空间解析。

在下一次运行中,我想在宏扩展时声明a(这是否有意义?),因此,在调用resolve时强制它出现在当前ns中。 / p>

(defmacro def&resolve [a b]
  (declare a)
  `(do (def ~a 12)
       (def ~b ~(resolve a))))

(def&resolve foo bar)
bar ;=> nil

也不起作用。

我该如何定义某些内容,并在宏扩展名称空间中对其进行解析?


[1]我的用例如下:我想定义一个函数束并将其添加到def绑定的元信息中(因此,在宏扩展时需要它)。目前,我只存储符号,没有存储定义函数的名称空间。

3 个答案:

答案 0 :(得分:0)

Sub colocar_Linha()
ultima_linha = Worksheets("Sheet2").Range("A3").CurrenRegion.Rows.count

i = 3

While i <= ultima_linha

    If Not (Cells(i, 1).value = Cells(i - 1, 1). value) Then

        Rows(i).Insert shift:=xlShiftDown

        i = i + 1
        ultima_linha = ultima_linha + 1;


    End If

    i = i + 1

Wend
End Sub

答案 1 :(得分:0)

由于将在运行时定义/创建变量,因此宏一旦完成工作并消失,宏就可以预测变量的名称并直接创建符号,而无需进行往返通过名称空间并返回

让我们先手动进行

user> (def foo)
#'user/foo
user> (resolve 'foo)
#'user/foo

看起来不错,现在让我们通过创建符号来做到这一点:

user> (symbol (str *ns* "/" "foo"))
user/foo

并将其复制到宏定义中:

user> (defmacro def&resolve [a b]
        `(do
           (def ~a 12)
           (def ~b ~(symbol (str *ns* "/" "foo")))))
#'user/def&resolve

进行测试

user> (def&resolve foo bar)
#'user/bar

user> bar
12

此方法优于在宏扩展时使用intern在虚拟空间中使用伪值创建符号的方法,然后在宏扩展时也使用resolve对其进行符号化。结果相同。这种方法的优势在于,它确实可以像您原始问题中那样在宏扩展时解决问题。

user> (do (intern *ns* 'a :dummy-value)
          (resolve 'a))
#'user/a

尽管我建议使用符号生成方法。

答案 2 :(得分:0)

语法引号的嵌套很有帮助,在〜a处附加引号:

(defmacro def&resolve
  [a b]
  `(do
     (def ~a 12)
     (def ~b ~`(resolve '~a))))
#'test-project.core/def&resolve

test-project.core=> (macroexpand '(def&resolve foo bar))
(do (def foo 12) (def bar (clojure.core/resolve (quote foo))))

test-project.core=> (def&resolve foo bar)
#'test-project.core/bar

test-project.core=> foo
12

test-project.core=> bar
#'test-project.core/foo

如果您实际上想获取foo的值,那么必须通过解析来对(@)var进行解引用:

(defmacro def&resolve
  [a b]
  `(do
     (def ~a 12)
     (def ~b @~`(resolve '~a))))

test-project.core=> (def&resolve foo bar)
#'test-project.core/bar
test-project.core=> bar
12