不,你不能使用元编程来将代码注入到已经写好的函数中。元编程只能做那些你可以直接在宏定义的位置手动编写的操作。这意味着像这样的语句:
@monitor(:z, 10); simulation(A, x)
无法修改
simulation(A, x)
函数调用,它只能扩展成一些普通的Julia代码在调用
simulation
之前运行。或许你可以将模拟函数调用作为宏的参数,例如
@monitor(:z, 10, simulation(A, x))
,但现在宏所能做的只是改变函数调用本身。它仍然不能“回到过去”并向已经编写好的函数添加新代码。
然而,您可以仔细地编写一个宏,取出函数定义体并修改它以添加您的调试代码,例如:
@monitor(:z, 10, function simulation(A, x)
for t in 1:1000
# ...
end
end)
但现在你必须在遍历函数体中的代码时编写
代码,并在正确位置注入调试语句。这不是一件容易的事情。而且要以健壮的方式编写,以免在修改实际仿真代码时立即出现错误。
使用编辑器自己遍历代码并插入代码比你要做的要容易得多。调试语句的常见习惯用法是使用单行语句,如下所示:
const debug = false
function simulation (A, x)
for t in 1:1000
z = rand(3)
x = A*x + z
debug && t%10==0 && append!(rec_z, z)
end
end
这里真正酷的是,通过将
debug
标记为常量,Julia能够在
false
时完全优化掉调试代码 - 它甚至不会出现在生成的代码中!因此,在没有调试时没有额外的开销。但这也意味着,您必须重新启动Julia(或重新加载它所在的模块)才能更改
debug
标志。即使
debug
没有被标记为
const
,我在这个简单的循环中也无法测量任何开销。而且你的循环很可能比这个更复杂。因此,在您确实检查它是否有影响之前,请不要担心性能问题。