以编程方式将参数传递给@kwdef struct [英] Pass arguments to @kwdef struct programmatically

查看:22
本文介绍了以编程方式将参数传递给@kwdef struct的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个结构:

Base.@kwdef struct example_struc
    Latitude::Float64  = 9.9        # Latitude (degree)
    Longitude::Float64 = -83.7      # Longitude (degree)
end

@kwdef 允许我实例化一个 example_struc() 而不提供所有参数,这要归功于默认设置,例如:

@kwdef allows me to instantiate an example_struc() without giving all arguments thanks to the defaults, e.g.:

julia> a= example_struc(Longitude= 40.0)
julia> a.Latitude
9.93833
julia> a.Longitude
40.0

我想通过将参数的名称及其值传递给 example_struc 以编程方式(从文件中读取的元组)实例化它.

I would like to instantiate it programmatically (from a tuple read in a file), by passing to example_struc the name of the argument, and its value.

我可以使用这样的元编程为一个参数做到这一点:

I can do it for one argument using metaprograming like this:

# Named tuple usually read from a file:
params= (Latitude = 43.61, Longitude = 3.877)
params_names= collect(keys(params))

lat= :($(params[1]))
lat_name= :($(params_names[1]))
e= :(example_struc($(lat_name)= $(lat)))
a= eval(e)

e 看起来像这样 :(example_struc(Latitude=43.61)),而 a 和之前一模一样.

e looks like this :(example_struc(Latitude=43.61)), and a is exactly as before.

现在,在我的例子中,参数的数量超过了两个(最多 50 个),所以我需要能够同时处理多个参数.所以我尝试使用 map 将函数参数作为一个整体传递:

Now in my case the number of arguments is more than two (up to 50), so I need to be able to do that for multiple arguments at once. So I tried passing the function arguments as a whole using map:

b= map((x,y) -> :($x = $y),params_names,params)
f= :(example_struc($(b...)))
eval(f)

f 看起来像这样::(example_struc(Latitude = 43.61, Longitude = 3.877))它有效,但这只是因为我们传递了所有参数:我们没有使用默认值.

f looks like this: :(example_struc(Latitude = 43.61, Longitude = 3.877)) And it works, but only because we pass all the arguments: we are not using the defaults.

现在如果我想为 Longitude 使用默认值,它不起作用:

Now if I want to use a default value for Longitude, it doesn't work:

b= map((x,y) -> :($x = $y),[params_names[1]],[params[1]])
f= :(example_struc($(b...)))
eval(f)

f 看起来像这样::(example_struc(Latitude = 43.61))但是现在出现错误:ERROR: MethodError: no method matching example_struc(::Float64)

f looks like this: :(example_struc(Latitude = 43.61)) But now there is an error : ERROR: MethodError: no method matching example_struc(::Float64)

所以不是像我期望的那样调用函数:example_struc(Latitude = 43.61),而是这样调用它:example_struc(43.61),没有参数名称.

So instead of calling the function like I would expect like this: example_struc(Latitude = 43.61), it calls it like this: example_struc(43.61), without the parameter name.

关于如何解决这个问题的任何想法?我对任何解决方案持开放态度,包括改变用户输入的方式(但必须简单).

Any idea on how to fix this ? I am open to any solution, including changing the way the user gives the inputs (but it has to be simple).

我正在 Julia 中编写一个程序,该程序读取可能包含 Julia 代码的用户输入文件(这是安全的,因为用户只在本地使用它).所以输入文件是一个 .jl 文件本身,它使用 evalfile 进行评估,用户在元组中提供参数值,例如:

I'm writing a program in Julia that read a user input file that possibly have Julia code in it (it is safe because the user only use it locally). So the input file is a .jl file itself that is evaluated using evalfile, and the user provide the parameter values in a Tuple, e.g.:

(
 Latitude::Float64  = 9.9,        # Latitude (degree)
 Longitude::Float64 = -83.7       # Longitude (degree)
 some_function= x -> x + 2        # Some functions can be defined by the user (if not, we use the default definition)
)

我的程序读取元组,我想提供一些默认值,eg如果用户只放Latitude,程序使用默认的经度 和默认some_function.为此,我使用 @kwdef 结构来利用其默认功能,但我需要知道如何以编程方式传递参数.

My program reads the Tuple, and I would like to provide some default values, e.g. if the user only put the Latitude, the program uses a default Longitude and default some_function. To do so, I use a @kwdef struct to leverage its default capabilities, but I need to know how to pass the arguments programmatically.

推荐答案

您应该能够将命名元组解包到构造函数的关键字参数位置.这是一个最小的例子:

You should be able to just unpack a named tuple into the keyword argument position of the constructor. Here's a minimal example:

julia> Base.@kwdef struct A
           x::Int64 = 1
           y::Int64 = 2
           z::Int64 = 3
       end
A

julia> kwargs = (z = 5, y = 4)
(z = 5, y = 4)

julia> A(; kwargs...)
A(1, 4, 5)

请注意,您需要在函数调用中使用分号来指示解压缩的参数是关键字参数.没有分号,你会得到一个方法错误:

Note that you need to use the semicolon in the function call to indicate that the unpacked arguments are keyword arguments. Without the semicolon, you'll get a method error:

julia> A(kwargs...)
ERROR: MethodError: no method matching A(::Int64, ::Int64)
Closest candidates are:
  A(::Int64, ::Int64, ::Int64) at REPL[13]:2
  A(::Any, ::Any, ::Any) at REPL[13]:2
Stacktrace:
 [1] top-level scope at none:0

查看这里了解更多详情关键字参数.

See here for more details on keyword arguments.

这篇关于以编程方式将参数传递给@kwdef struct的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆