繁体   English   中英

如何从`String`s 或`Symbol`s 列表创建一个`Enum`?

[英]How can I create an `Enum` from a list of `String`s or `Symbol`s?

给定String的列表

my_list = ["Banana", "Orange", "Apple"]

如何创建“相应的” Enum对象? 我正在寻找看起来像的东西

@enum MyEnum my_list # does not work

这相当于

@enum MyEnum Banana Orange Apple

尝试这个:

julia> Main.eval(Meta.parse("@enum MyEnum $(join(my_list, " "))"))

julia> MyEnum
Enum MyEnum:
Banana = 0
Orange = 1
Apple = 2

我尝试翻译@enum宏,然后得出以下结论:

如果您创建一个名为MyEnum且实例 a=1,b=2,c=3 的 Enum,则@enum宏生成的代码是:

primitive type MyEnum <: Base.Enums.Enum{Int32} 32 end 
function MyEnum(x::Integer)
    1<=x<=3 || Base.Enums.enum_argument_error(MyEnum,x)
    return Base.bitcast(MyEnum, convert(Int32, x))
end

Base.Enums.namemap(x::Type{MyEnum}) = Dict{Int32,Symbol}(1=>:a,2=>:b,3=>:c)Base.typemin(x::Type{MyEnum}) = MyEnum(1)
Base.typemax(x::Type{MyEnum}) = MyEnum(3)const a = MyEnum(1)
const b = MyEnum(2)
const c = MyEnum(3)
Base.instances(x::Type{MyEnum}) = (a,b,c)

如果我们已经确定了 Enum 的名称并有一个String列表,我们可以按如下方式进行:

enum_namemap = Dict(Int32(k)=>v for (k,v) in pairs(Symbol.(my_list)))
const myenum_lo = 1
const myenum_hi = length(enum_namemap)

primitive type MyEnum <: Base.Enums.Enum{Int32} 32 end 
function MyEnum(x::Integer)
    myenum_lo<=x<=myenum_hi || Base.Enums.enum_argument_error(MyEnum,x)
    return Base.bitcast(MyEnum, convert(Int32, x))
end

Base.Enums.namemap(x::Type{MyEnum}) = enum_namemap
Base.typemin(x::Type{MyEnum}) = MyEnum(myenum_lo)
Base.typemax(x::Type{MyEnum}) = MyEnum(myenum_hi)

for (k,v) pairs(enum_namemap)
@eval begin
  const $v= MyEnum($k)
end

const = myenum_instances = ([MyEnum(v) for v in keys(enum_namemap)]...)
@eval begin
  Base.instances(x::Type{MyEnum}) = $myenum_instances 
end

使用Symbol列表,代码更容易,因为没有任何到Symbol的转换

可悲的是,我无法直接向@enum宏提供字典或名称列表,这将是最简单的形式

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM