Let\'s say I want to have a function of the form
abstract RecordType
function CreateRecordType(fields_names::Vector{ASCIIString}, type_name::ASCIIString)
# m
Probably the easiest way is to create a string of what you want and then parse it to get an AST, and then eval the AST. You can do any or all within the function. Here's possible simple implementation that does it all
function CreateRecordType(typeName::ASCIIString,fieldNames::Array{ASCIIString,1},fieldTypes::Array{ASCIIString,1})
s::ASCIIString = "type $typeName <: RecordType\n";
for i = 1:length(fieldNames)
s = s*"$(fieldNames[i])::$(fieldTypes[i])\n"
end
eval(parse(s*"end"));
return;
end
julia> abstract RecordType;
julia> CreateRecordType("Person",["name","age"],["ASCIIString","Int64"])
julia> bubba = Person("Bubba",2)
Person("Bubba",2)
julia> print(bubba.age)
2
That's probably not as efficient as it could be, instead you can take a look at the AST that parse produces and then create the Expr to make the AST directly and not use parse and not use a string.
Here's an alternate form that creates an AST, it's a little more safe because it requires types and symbols rather than opaque strings. This was created by experimenting with the output of various parses as alluded to above. Using Dict instead of 2 arrays is probably better because the field and the type must always be paired.
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