在运行时可以在Julia中创建类型吗?
问题描述:
比方说,我想有形式在运行时可以在Julia中创建类型吗?
abstract RecordType
function CreateRecordType(fields_names::Vector{ASCIIString}, type_name::ASCIIString)
# magic that creates the type type_name with string fields field_names
end
例如,CreateRecordType(["name","age"], "Person")
将创建一个新的类型,定义如下的功能:
type Person <: RecordType
name::ASCIIString
age::ASCIIString
end
这是可能在朱莉亚办?
答
方法1:解析得到一个AST,然后EVAL
也许最简单的方法是创建你想要什么字符串,然后解析它得到一个AST,然后EVAL的AST。你可以做任何或全部的功能。下面是可能的简单的实现,所有这一切
使用它...
julia> abstract RecordType;
julia> CreateRecordType("Person",["name","age"],["ASCIIString","Int64"])
julia> bubba = Person("Bubba",2)
Person("Bubba",2)
julia> print(bubba.age)
2
这可能效率不高,因为它可以代替你可以看看那个解析产生和AST然后创建Expr以直接创建AST并且不使用解析并且不使用字符串。
方法2:使AST直接
下面是创建AST的另一种形式,它是一个小更安全,因为它需要的类型和符号,而不是不透明的字符串。这是通过试验上面提到的各种解析的输出而创建的。使用Dict而不是2个数组可能更好,因为字段和类型必须始终配对。在行动
function createTypeAST(typeName::Symbol,parentType::Type,fields::Dict{Symbol,DataType})
e = Expr(:type,true)
push!(e.args,Expr(:<:));
push!(e.args[2].args,typeName);
push!(e.args[2].args,parentType);
push!(e.args,Expr(:block))
for field in fields
push!(e.args[3].args,:($(field[1])::$(field[2])));
end
return e;
end
第二形式
julia> x = createTypeAST(:P1,RecordType,Dict(:a => Int64))
:(type P1<:RecordType
a::Int64
end)
julia> eval(x)
julia> y = P1(1)
P1(1)
julia> y.a
1