是否可以在运行时在 Julia 中创建类型? [英] Is it possible to create types in Julia at runtime?

查看:23
本文介绍了是否可以在运行时在 Julia 中创建类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我想拥有表单的功能

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

例如,CreateRecordType(["name","age"], "Person") 将创建一个具有以下定义的新类型:

For example, CreateRecordType(["name","age"], "Person") would create a new type with the following definition:

type Person <: RecordType
    name::ASCIIString
    age::ASCIIString
end

这可能在 Julia 中实现吗?

Is this possible to do in Julia?

推荐答案

方法一:解析得到一个AST,然后求值

可能最简单的方法是创建一个你想要的字符串,然后解析它以获得一个 AST,然后评估 AST.您可以在函数内执行任何或所有操作.这里有一个可能的简单实现,可以做到这一切

Approach 1: Parse to get an AST and then eval

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
";

   for i = 1:length(fieldNames)
      s = s*"$(fieldNames[i])::$(fieldTypes[i])
"
   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

这可能没有它应该的效率那么高,相反,您可以查看 parse 生成的 AST,然后创建 Expr 以直接生成 AST 而不是使用 parse 而不是使用 a字符串.

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.

这是创建 AST 的另一种形式,它更安全一些,因为它需要类型和符号而不是不透明的字符串.这是通过尝试上面提到的各种解析的输出来创建的.使用 Dict 而不是 2 个数组可能会更好,因为字段和类型必须始终配对.

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

这篇关于是否可以在运行时在 Julia 中创建类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆