这与David的问题here有些相关。我有兴趣循环遍历符号数组(指向对象)并对循环的每一步执行操作。例如,假设我想编写一个查看一堆变量并将任何标量转换为单元素数组的函数。
widget = "a scalar"
dohickey = ["item 1", "item 2"]
gizmo = "another scalar"
theVariables = [:widget, :dohickey, :gizmo]
for thisVariable in theVariables
if !(typeof(eval(thisVariable)) <: Array)
println("Found a scalar")
#Make it a vector here
end
end
理想情况下,最后我们会有以下内容
widget = ["a scalar"]
dohickey = ["item 1", "item 2"]
gizmo = ["another scalar"]
这是一个相当蹩脚的例子,但如何做到这一点?我以为我应该可以使用像
这样的东西:($thisVariable) = [:($thisVariable)]
但我无法让它发挥作用。
编辑:下面的DSM解决方案适用于上述情况,但在我的实际使用中,我想在一个函数内执行此操作。如果我定义
function getsort(; arga="", argb="", argc="")
filterSpecs = [:arga, :argb, :argc]
for ts in filterSpecs
if !(typeof($ts) <: Array)
#nothing here
end
end
end
然后调用getsort()抛出
error compiling getsort: error compiling __getsort#31__: syntax: prefix $ in non-quoted expression
我显然错过了有关元编程魔法的一些信息。
答案 0 :(得分:4)
这更像是@ DSM答案的后续内容,但在评论中编写代码很难。需要注意的是:eval
在全局范围内进行评估,这会导致奇怪的事情
julia> a = 3
3
julia> function f(a)
eval(:(a = 1))
println(a)
end
f (generic function with 1 method)
julia> f(a)
3
julia> a
1
答案 1 :(得分:3)
从文档的code generation部分,我认为您需要的只是
@eval $thisVariable = [$thisVariable]
例如:
widget = "a scalar"
dohickey = ["item 1", "item 2"]
gizmo = "another scalar"
theVariables = [:widget, :dohickey, :gizmo]
for thisVariable in theVariables
if !(typeof(eval(thisVariable)) <: Array)
println("Found a scalar")
@eval $thisVariable = [$thisVariable]
end
end
给了我
Found a scalar
Found a scalar
julia> widget
1-element Array{ASCIIString,1}:
"a scalar"
julia> dohickey
2-element Array{ASCIIString,1}:
"item 1"
"item 2"
julia> gizmo
1-element Array{ASCIIString,1}:
"another scalar"
答案 2 :(得分:2)
你确定你需要一个宏吗?如果您只想处理功能输入,可以执行以下操作:
julia> function newDictOfArrays(d)
wrapped=false
for (k,v) in d
if !(typeof(v) <: AbstractArray)
wrapped = true
d[k] = [v]
end
end
(wrapped, d)
end
newDictOfArrays (generic function with 1 method)
julia> function f(; kwargs...)
(wrapped, d) = newDictOfArrays(Dict(kwargs))
if wrapped
return f(;d...)
end
println("continue knowing all keyword args have been wrapped: $kwargs")
end
f (generic function with 1 method)
julia> f(a=1, b=[2])
continue knowing all keyword args have been wrapped: Any[(:a,[1]),(:b,[2])]
julia> f(a=[1], b=[2])
continue knowing all keyword args have been wrapped: Any[(:a,[1]),(:b,[2])]
newDictOfArrays检查字典的所有成员以查找不是AbstractArray的子类型的值,并使用包装值覆盖该项目。在f中,如果有任何东西被包装,它会再次使用作为关键字参数传递的新字典重新调用相同的函数。没有宏,eval等,尽管你可以考虑编写一个宏,如果经常需要这个宏,会自动将代码注入f。