在Julia中将公式作为函数参数传递

Cas*_*sey 5 anonymous-function julia

我正在尝试创建一个允许更改Julia中的公式和系数的函数.我80%确定我应该使用匿名函数吗?

这个使用python的SO帖子是我想要完成的一个更离散的例子(特别是chepner的基本python示例,而不是使用库).在python中将公式作为函数参数传递

我还发现这个使用Julia的SO帖子,它使用一个类型来存储所需的参数,然后将它们传递给一个函数.如何将参数列表传递给Julia中的函数

使用这些作为基础,这是我到目前为止创建的:

   #Create composite type
   type Params
   formula
   b1::Float64
   b2::Float64
   end

   #create instance of type and load
    foo=Params((b1,b2,X)-> X^b1+X+b2,0.004,0.005)

   #create function
   function DoMath(X,p::Params)
   p.formula(X,varargs...) #??
   end 
Run Code Online (Sandbox Code Playgroud)
  1. 我是否正确地通过使用复合类型和/或lambdas来构建它?我没有任何CS培训,在尝试学习Julia的过程中,我在弄清楚了许多概念.

  2. 什么是允许用户更改公式和任何系数的函数的正确语法.对于给定的X?最终,我想象的功能如下:

    DoMath(4) #some default formula with changing X
    DoMath(4, X*b1 +X*b2) #change X and change formula 
    DoMath(4, (X,b1,b2,b3)->X*b1+X*b2+x*b3) # change x, change formula to   a 3 parameter function
    
    Run Code Online (Sandbox Code Playgroud)

谢谢

更新: 我按照@Chris的语法开始工作.我不得不修补的一件事是使用

   (p::Params)(x) = p.formula(x,p.b) #p.b, not just b otherwise error
Run Code Online (Sandbox Code Playgroud)

我必须在调用之前将2.0和3.0包装在一个数组中

   p = Params((x,b)->x*b[1]+b[2],[2.0,3.0])
Run Code Online (Sandbox Code Playgroud)

Chr*_*kas 12

我们的想法是建立一个可调用的类型.可调用类型是具有"调用"的任何类型.函数f是可调用类型,因为您可以调用它:f(x)例如.但是,函数不是唯一可以像函数一样运行的东西.实际上,在Julia中,函数基本上是可调用的类型<: Function.

所以让我们为你的例子构建一个.使您的类型包含您想要的数据:

type Params
  b1::Float64
  b2::Float64
end
Run Code Online (Sandbox Code Playgroud)

现在让我们添加一个调用Params.让我们说我们想做x*b1 + b2.我们可以通过以下方式拨打电话:

(p::Params)(x) = x*p.b1 + p.b2
Run Code Online (Sandbox Code Playgroud)

让我们看看它是如何工作的.做一个参数:

p = Params(2.0,3.0)
Run Code Online (Sandbox Code Playgroud)

现在我们可以通过使用它的调用来计算公式:

p(4) # 4*2+3 = 11
Run Code Online (Sandbox Code Playgroud)

现在看到它p充当使用内部数据的函数.就是这个.

其余的都是从同一个基础建立起来的.您需要尊重Julia类型不是动态的事实.这是有充分理由的.但是,假设你不知道你想要多少b.然后你可以让一个字段成为一个数组b:

type Params
  b::Vector{Float64}
end
(p::Params)(x) = x*b[1] + b[2]
Run Code Online (Sandbox Code Playgroud)

现在让我们假设您希望能够修改公式.然后你可以有一个公式字段:

type Params
  formula
  b::Vector{Float64}
end
Run Code Online (Sandbox Code Playgroud)

并使调用将值抛出到:

(p::Params)(x) = p.formula(x,b)
Run Code Online (Sandbox Code Playgroud)

现在,如果用户做了:

p = Params((x,b)->x*b[1]+b[2],2.0,3.0)
Run Code Online (Sandbox Code Playgroud)

然后,和以前一样:

p(4) # 4*2+3 = 11
Run Code Online (Sandbox Code Playgroud)

它的行为相同,仍然使用内部数据.

但由于p只是任何类型,我们可以修改字段.所以在这里我们可以修改:

p.formula = (x,b)-> x*b[1]+x*b[2]+b[3]
push!(p.b,2.0) # p.b == [2.0,3.0,2.0]
Run Code Online (Sandbox Code Playgroud)

并再次调用,现在使用更新的字段:

p(4) # 4*2 + 4*3 + 2 = 22
Run Code Online (Sandbox Code Playgroud)

实际上,正如@LyndonWhite指出的那样,ParameterizedFunctions.jl实现了这样的东西.这样做的策略是可调用类型.

额外的小细节

构建(错误地)某些库需要用户传入函数.所以这里我们有一个p"就像一个函数",但有些库不会接受它.

但是,有一个快速解决方案.做吧<:Function.例:

type Params <: Function
  b1::Float64
  b2::Float64
end
Run Code Online (Sandbox Code Playgroud)

现在需要一个功能的东西会把你p当成一个<:Function.这只是一种指出在Julia中Function是一种抽象类型的方法,每种function都只是一种可调用的子类型Function.