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

查看:48
本文介绍了是否可以在运行时在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

这在朱莉娅有可能吗?

推荐答案

方法1:解析以获取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\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

这可能没有效率那么高,相反,您可以查看解析产生的AST,然后创建 Expr 以直接制作AST,而不使用解析而不使用字符串.

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天全站免登陆