Let's say I want to have a function of the form
abstract RecordType
function CreateRecordType(fields_names::Vector{ASCIIString}, type_name::ASCIIString)
# magic that creates the type type_name with string fields field_names
end
For example, CreateRecordType(["name","age"], "Person")
would create a new type with the following definition:
type Person <: RecordType
name::ASCIIString
age::ASCIIString
end
Is this possible to do in Julia?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With