Macros julia元编程与nloops变量求值
我是元编程的noob,所以可能我不理解这一点。我认为Macros julia元编程与nloops变量求值,macros,julia,metaprogramming,Macros,Julia,Metaprogramming,我是元编程的noob,所以可能我不理解这一点。我认为@nloops宏在Base.Cartesian中的作用是,在维度未知的情况下,为循环编写任意数量的嵌套代码。在模块的文档中,给出了以下示例: @nloops 3 i A begin s += @nref 3 A i end 评估结果是 for i_3 = 1:size(A,3) for i_2 = 1:size(A,2) for i_1 = 1:size(A,1) s += A[i_1,
@nloops
宏在Base.Cartesian
中的作用是,在维度未知的情况下,为循环编写任意数量的嵌套代码。在模块的文档中,给出了以下示例:
@nloops 3 i A begin
s += @nref 3 A i
end
评估结果是
for i_3 = 1:size(A,3)
for i_2 = 1:size(A,2)
for i_1 = 1:size(A,1)
s += A[i_1,i_2,i_3]
end
end
end
在这里,数字3是先验的。然而,出于我的目的,以及我认为创建NLOOP的目的,嵌套级别的数量事先并不知道。所以我无法硬编码整数3。即使在文件中,也说明:
@nloops的(基本)语法如下:
- 第一个参数必须是指定循环数的整数(不是变量)
b = 3
@nloops b i A begin
s += @nref b A i
end
这将返回一个错误:
ERROR: LoadError: MethodError: no method matching _nloops(::Symbol, ::Symbol, ::Symbol, ::Expr)
Closest candidates are:
_nloops(::Int64, ::Symbol, ::Symbol, ::Expr...) at cartesian.jl:43
...
我不知道如何让nloops将b
变量计算为整数而不是符号。我查看了文档并尝试了eval
以及其他函数和宏的各种迭代,但它要么被解释为符号,要么被解释为Expr
。朱利安,写这篇文章的正确方法是什么?参见:
生成的函数有点像宏,因为生成的表达式不会返回,而是在调用/调用时编译和执行,它还会看到参数的类型(当然还有它们的类型参数),即:
- 在生成的函数中,
是A
,不是数组的值数组{T,N}
- 所以
是T
,Int
是N
李>3
N
插入表达式,语法为$N
,计算结果为3
:
julia> @generated function mysum(A::Array{T,N}) where {T,N}
quote
s = zero(T)
@nloops $N i A begin
s += @nref $N A i
end
s
end
end
mysum (generic function with 1 method)
julia> mysum(A)
23.2791638775186
您可以构造表达式,然后对其求值,即:
julia> s = 0; n = 3;
julia> _3loops = quote
@nloops $n i A begin
global s += @nref $n A i
end
end
quote
@nloops 3 i A begin
global s += @nref(3, A, i)
end
end
julia> eval(_3loops)
julia> s
23.2791638775186
我已经从AST中手动删除了LineNumberNode
s以提高可读性(还有MacroTools.prettify
,这可以为您完成)
在REPL中运行此示例需要在Julia 1.0中的循环内将s
声明为global
julia> s = 0; n = 3;
julia> _3loops = quote
@nloops $n i A begin
global s += @nref $n A i
end
end
quote
@nloops 3 i A begin
global s += @nref(3, A, i)
end
end
julia> eval(_3loops)
julia> s
23.2791638775186