在运行时可以在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