Types Julia Design:在宏中静默定义/命名类型
在定义新特性时,我遇到了一个开发问题,即如何“无声地定义类型”。目前我有一些宏,比如:Types Julia Design:在宏中静默定义/命名类型,types,macros,julia,Types,Macros,Julia,在定义新特性时,我遇到了一个开发问题,即如何“无声地定义类型”。目前我有一些宏,比如: f = @ode_define begin dx = a*x - b*x*y dy = -c*y + d*x*y end a=>1.5 b=>1 c=3 d=1 这将扩展到 f = (t,u,du) -> begin du[1] = 1.5*u[1] - u[1]*u[2] du[2] = -3*u[2] + u[1]*u[2] end 这些定义了ODE解算器中使用的函数。ODE解算器
f = @ode_define begin
dx = a*x - b*x*y
dy = -c*y + d*x*y
end a=>1.5 b=>1 c=3 d=1
这将扩展到
f = (t,u,du) -> begin
du[1] = 1.5*u[1] - u[1]*u[2]
du[2] = -3*u[2] + u[1]*u[2]
end
这些定义了ODE解算器中使用的函数。ODE解算器的某些功能需要了解参数(即敏感性分析需要获取参数导数),因此为了使其更通用,我希望内联使用=
定义的参数,并使用=>
定义的“命名访问”参数。例如,我想将宏扩展为:
f,p = (t,u,du,p) -> begin
du[1] = p.a*u[1] - p.b*u[1]*u[2]
du[2] = -3*u[2] + u[1]*u[2]
end
问题是,如何定义参数?我可以让宏也执行以下操作:
type Parameters
a::Float64
b::Float64
end
p = Parameters(a,b)
然后,每个会话只能使用宏一次,因为每次都需要定义参数类型。是否有一种安全的方法来命名此类型,以便可以重复使用宏?从本质上讲,参数类型除了它是包含a
和b
的内容的容器,并且可以通过名称进行访问(这一点非常重要,因为我计划做一些事情,询问您希望对哪些参数执行操作,如分叉图)。这就是我所说的“静默”的意思——我希望宏吐出一个p
,其中p.a
和p.b
起作用,无需参考/用户不必关心这是如何定义的。此外,此设计路径还有一个限制,即不能在函数内部定义类型,因此此宏不能用于在函数内部定义ODE函数
Julia是否提供了一种不牺牲性能的解决这些问题的好方法?(我可以使用字典,但这会导致性能下降)
编辑 为了总结设计目标,我需要一些东西,以便像我在开始时展示的宏可以编写如下代码:
f,p = (t,u,du,p) -> begin
du[1] = p.a*u[1] - p.b*u[1]*u[2]
du[2] = -3*u[2] + u[1]*u[2]
end
type Parameters
a::Float64
b::Float64
end
p = Parameters(a,b)
召唤
solve(f,p,y0)
在基本上
for i = 1:numiterations
y = y + dt*f(t,u,du,p)
end
问题在于
p
的正确形式是否是一种类型,或者朱莉娅是否有其他东西可以“用名字来称呼事物”。如果它是一个类型,那么如何避免类型必须具有唯一的名称(这样宏就不能简单地将其扩展为类型参数,因为每次它可能有不同的字段),而是如何在您只知道字段名称的情况下自动生成类型?gensym
创建全局唯一的名称,可以拼接到类型定义表达式中,例如:
Expr(:type, true, gensym(:parameter), Expr(:(::), :x, :Int))
我可以用字典,但那会影响性能
我不完全确定我是否理解这里的设计目标,但在您的示例中,您将实例
p
包装在闭包中。如果将ODE名称设置为宏参数(@ODE_def=…
),则可以在某个全局字典中从f=>f_metadata
设置映射,该映射带有p
的句柄以及可能需要修改的任何内容。我在编辑中添加了一些详细信息。我尝试了typegensym(:parameters)
和a
和b
字段,但它说这是无效的类型签名。是否有方法使用gensym
生成可用于类型签名的表达式?更新以回答特定类型名称问题。就一般设计问题而言:对于被积函数/目标函数,参数闭包是非常合理的。但是,对于解算器使用的可修改参数,而不是目标函数中使用的一次性常量,关闭某些不透明类型是没有意义的。我认为这可能会起作用。我需要添加类型的主要原因是,我可以进行参数敏感性分析,这需要在参数中使用导数。我希望能够告诉解算器“给我参数a
中的灵敏度”,从而获得a
中的参数导数。如果在闭包中指定了参数,我不知道该怎么做。但同时,参数的类型并不重要,只是它有一个字段a
。