在 Julia 中迭代具有不同数量参数的不同函数
Iterating over different functions with different number of parameters in Julia
我正在尝试 运行 对具有不同数量参数的不同函数进行循环。变量是在循环内的 运行 时间创建的,我想在每次迭代中使用 eval 来使用变量 :symbol 实例化一个 Struct。但是,我不能这样做,因为 eval 只适用于全局范围。这是适用于案例的 MWE:
function f1(x); return x; end
function f2(x1,x2); return x1+x2; end
handles = [f1,f2]
args =[:(x1),:(x1,x2)]
x1 = 1; x2 = 1;
for (i,f) in enumerate(handles)
params = eval(args[i])
@show f(params...)
end
f(params...) = 1
f(params...) = 2
但是,如果我在循环内移动变量定义,这正是我真正想要的,在重新启动 Julia 以清除工作区后它不起作用。
function f1(x); return x; end
function f2(x1,x2); return x1+x2; end
handles = [f1,f2]
args =[:(x1),:(x1,x2)]
for (i,f) in enumerate(handles)
x1 = 1; x2 = 1;
params = eval(args[i])
@show f(params...)
end
ERROR: UndefVarError: x1 not defined
我已经尝试了几个答案,例如 this one,但我似乎无法让它发挥作用。我可以编写一个自定义调度函数,它接受 [x1,x2] 并使用正确的参数调用 f1 或 f2。但是,有没有办法用 eval 或其他优雅的解决方案来做到这一点?
编辑:这里有更多关于我在我的代码中尝试做的事情的细节。我为每个算法都有一个配置结构,在此我想预先定义它需要的参数
KMF_config = AlgConfig(
name = "KMF",
constructor = KMC.KMF,
parameters = :(mu,N,L,p),
fit = KMC.fit!)
MF_config = AlgConfig(
name = "MF",
constructor = KMC.MF,
parameters = :(mu,N,L),
fit = KMC.fit!)
alg_config_list = [KMF_config, MF_config]
for (i,alg_config) in enumerate(alg_config_list)
mu,N,L,p,A,B,C,D,data = gen_vars() #this returns a bunch of variables that are used in different algorithms
method = alg_config.constructor(eval(method.parameters)...)
method.fit(data)
end
一个可能的解决方案是让一个函数获取所有变量和方法,并且 return 一个包含根据 method.name 的变量子集的元组。但我不确定这是否是最好的方法。
这是一种使用多重分派而不是 eval
的方法:
run_a(x, y) = x + 10*y
run_b(x, y, z) = x + 10*y + 100*z
extract(p, ::typeof(run_a)) = (p.x, p.y)
extract(p, ::typeof(run_b)) = (p.x, p.y, p.z)
genvars() = (x=1, y=2, z=3)
function doall()
todo = [
run_a,
run_b,
]
for runalg in todo
v = genvars()
p = extract(v, runalg)
@show runalg(p...)
end
end
在您的示例中,您会将 run_a
和 run_b
替换为 KMC.KMF
和 KMC.MF
。
编辑:清理示例以避免示例中不存在的结构。
我正在尝试 运行 对具有不同数量参数的不同函数进行循环。变量是在循环内的 运行 时间创建的,我想在每次迭代中使用 eval 来使用变量 :symbol 实例化一个 Struct。但是,我不能这样做,因为 eval 只适用于全局范围。这是适用于案例的 MWE:
function f1(x); return x; end
function f2(x1,x2); return x1+x2; end
handles = [f1,f2]
args =[:(x1),:(x1,x2)]
x1 = 1; x2 = 1;
for (i,f) in enumerate(handles)
params = eval(args[i])
@show f(params...)
end
f(params...) = 1
f(params...) = 2
但是,如果我在循环内移动变量定义,这正是我真正想要的,在重新启动 Julia 以清除工作区后它不起作用。
function f1(x); return x; end
function f2(x1,x2); return x1+x2; end
handles = [f1,f2]
args =[:(x1),:(x1,x2)]
for (i,f) in enumerate(handles)
x1 = 1; x2 = 1;
params = eval(args[i])
@show f(params...)
end
ERROR: UndefVarError: x1 not defined
我已经尝试了几个答案,例如 this one,但我似乎无法让它发挥作用。我可以编写一个自定义调度函数,它接受 [x1,x2] 并使用正确的参数调用 f1 或 f2。但是,有没有办法用 eval 或其他优雅的解决方案来做到这一点?
编辑:这里有更多关于我在我的代码中尝试做的事情的细节。我为每个算法都有一个配置结构,在此我想预先定义它需要的参数
KMF_config = AlgConfig(
name = "KMF",
constructor = KMC.KMF,
parameters = :(mu,N,L,p),
fit = KMC.fit!)
MF_config = AlgConfig(
name = "MF",
constructor = KMC.MF,
parameters = :(mu,N,L),
fit = KMC.fit!)
alg_config_list = [KMF_config, MF_config]
for (i,alg_config) in enumerate(alg_config_list)
mu,N,L,p,A,B,C,D,data = gen_vars() #this returns a bunch of variables that are used in different algorithms
method = alg_config.constructor(eval(method.parameters)...)
method.fit(data)
end
一个可能的解决方案是让一个函数获取所有变量和方法,并且 return 一个包含根据 method.name 的变量子集的元组。但我不确定这是否是最好的方法。
这是一种使用多重分派而不是 eval
的方法:
run_a(x, y) = x + 10*y
run_b(x, y, z) = x + 10*y + 100*z
extract(p, ::typeof(run_a)) = (p.x, p.y)
extract(p, ::typeof(run_b)) = (p.x, p.y, p.z)
genvars() = (x=1, y=2, z=3)
function doall()
todo = [
run_a,
run_b,
]
for runalg in todo
v = genvars()
p = extract(v, runalg)
@show runalg(p...)
end
end
在您的示例中,您会将 run_a
和 run_b
替换为 KMC.KMF
和 KMC.MF
。
编辑:清理示例以避免示例中不存在的结构。