如果我有方法
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
如果我写这个的话就可以了
@doarray([x])
或
@doarray([:x])
,但以下代码正确地行不通,从而提高了ArgumentError
(即ArgumentError: alist should be a vector
)。
alist = [:x]
@doarray(alist)
如何使上述内容与@doarray([x])相似
动机:
我有一个递归宏(例如mymacro
),它使用一个向量,对第一个值进行运算,然后用向量的其余部分(例如mymacro
)递归调用rest_vector
。我可以创建rest_vector
,正确打印值(用于调试),但是当我再次将其馈送到rest_vector
时,我不知道如何求值mymacro
。
编辑1: 我正在尝试在Julia中实现logic programming,即MiniKanren。在我以此为基础的Clojure实现中,代码就是这样。
(defmacro fresh
[var-vec & clauses]
(if (empty? var-vec)
`(lconj+ ~@clauses)
`(call-fresh (fn [~(first var-vec)]
(fresh [~@(rest var-vec)]
~@clauses)))))
基于此的我失败的Julia代码如下。如果这没有意义,我深表歉意,因为我正在尝试通过实现宏来理解宏。
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)
)
ERROR: LoadError: LoadError: UndefVarError: varvecvest not defined
问题行为fn = $(esc(varvec.args[1])) -> @fresh($(varvecvest), $(esc(clauses)))
答案 0 :(得分:1)
如果我正确理解了您的问题,最好在宏内调用一个函数(而不是宏),该函数将对传递给该宏的AST进行操作。这是一个简单的示例,您如何做到:
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
当然,在此示例中,我们没有做任何有用的事情。如果您确切说明了要实现的目标,那么我可能会建议更具体的内容。