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