首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在执行宏之前将变量传递给宏并对其求值?

如何在执行宏之前将变量传递给宏并对其求值?
EN

Stack Overflow用户
提问于 2018-11-23 10:56:24
回答 1查看 93关注 0票数 1

如果我有一个方法

代码语言:javascript
复制
macro doarray(arr)
    if in(:head, fieldnames(typeof(arr))) && arr.head == :vect
        println("A Vector")
    else
        throw(ArgumentError("$(arr) should be a vector"))
    end
end

如果我写这篇文章,它就会起作用

代码语言:javascript
复制
@doarray([x])

代码语言:javascript
复制
@doarray([:x])

但是下面的代码不能正常工作,引发ArgumentError(即ArgumentError: alist should be a vector)。

代码语言:javascript
复制
alist = [:x]
@doarray(alist)

我怎样才能使上面的代码类似于@doarray(x)

动机:我有一个递归宏(比方说mymacro),它接受一个向量,对第一个值进行操作,然后用向量的其余部分递归调用mymacro (比方说rest_vector)。我可以创建rest_vector,正确地打印值(用于调试),但是当我再次将rest_vector提供给mymacro时,我不知道如何计算它。

编辑1:我正在尝试在Julia中实现logic programming,即MiniKanren。在我所基于的Clojure实现中,代码是这样的。

代码语言:javascript
复制
(defmacro fresh
  [var-vec & clauses]
  (if (empty? var-vec)
    `(lconj+ ~@clauses)
    `(call-fresh (fn [~(first var-vec)]
                   (fresh [~@(rest var-vec)]
                     ~@clauses)))))

我失败的Julia代码基于这一点,如下。如果它没有意义,我道歉,因为我试图通过实现它来理解宏。

代码语言:javascript
复制
macro fresh(varvec, clauses...)
    if isempty(varvec.args)
        :(lconjplus($(esc(clauses))))
    else
        varvecrest = varvec.args[2:end]
        return quote
            fn = $(esc(varvec.args[1])) -> @fresh($(varvecvest), $(esc(clauses)))
            callfresh(fn)
        end
    end
end

运行代码@fresh([x, y], ===(x, 42))时得到的错误(在本文中您可以忽略===(x, 42) )

代码语言:javascript
复制
ERROR: LoadError: LoadError: UndefVarError: varvecvest not defined

问题行是fn = $(esc(varvec.args[1])) -> @fresh($(varvecvest), $(esc(clauses)))

EN

回答 1

Stack Overflow用户

发布于 2018-11-23 15:36:33

如果我正确理解了您的问题,最好在宏内调用一个函数(而不是宏),该函数将在传递给宏的AST上操作。下面是一个简单的例子,你可以做到这一点:

代码语言:javascript
复制
function recarray(arr)
    println("head: ", popfirst!(arr.args))
    isempty(arr.args) || recarray(arr)
end

macro doarray(arr)
    if in(:head, fieldnames(typeof(arr))) && arr.head == :vect
        println("A Vector")
        recarray(arr)
    else
        throw(ArgumentError("$(arr) should be a vector"))
    end
end

当然,在这个例子中,我们没有做任何有用的事情。如果你具体说明了你想要实现的目标,那么我可能会提出更具体的建议。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53440146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档