2014-11-22 110 views
9

比方說,我想有形式在運行時可以在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 

這是可能在朱莉亞辦?

回答

6

方法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 
相關問題