假设我想要一个表单的功能
abstract RecordType
function CreateRecordType(fields_names::Vector{ASCIIString}, type_name::ASCIIString)
# magic that creates the type type_name with string fields field_names
end
Run Code Online (Sandbox Code Playgroud)
例如,CreateRecordType(["name","age"], "Person")将使用以下定义创建一个新类型:
type Person <: RecordType
name::ASCIIString
age::ASCIIString
end
Run Code Online (Sandbox Code Playgroud)
朱莉娅有可能吗?
可能最简单的方法是创建一个你想要的字符串,然后解析它以获得AST,然后评估AST.您可以在该功能中执行任何或所有操作.这可能是简单的实现,可以完成所有工作
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
Run Code Online (Sandbox Code Playgroud)
julia> abstract RecordType;
julia> CreateRecordType("Person",["name","age"],["ASCIIString","Int64"])
julia> bubba = Person("Bubba",2)
Person("Bubba",2)
julia> print(bubba.age)
2
Run Code Online (Sandbox Code Playgroud)
这可能没那么高效,相反你可以看一下解析产生的AST,然后创建Expr直接生成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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)