2

I am newbie in Julia language, and the tutorial is not very deep yet and I didn't understand what is the best way to pass a parameter list of a function. My function looks like this:

function dxdt(x)
    return a*x**2 + b*x - c
end

where x is the variable (2D array) and a,c, and d are parameters. As I understand it is not recommended to work with global variables in Julia. So what is the right way to do it?

Ohm
  • 2,312
  • 4
  • 36
  • 75
  • 3
    if the parameter list is complex, you can use [optional arguments](http://julia.readthedocs.org/en/latest/manual/functions/#optional-arguments) and [keyword arguments](http://julia.readthedocs.org/en/latest/manual/functions/#keyword-arguments) to avoid passing the whole list every time. – Gnimuc Oct 06 '15 at 16:15

5 Answers5

4

The idiomatic solution would be to create a type to hold the parameters and use multiple dispatch to call the correct version of the function.

Here's what I might do

type Params
    a::TypeOfA
    b::TypeOfB
    c::TypeOfC
end

function dxdt(x, p::Params)
    p.a*x^2 + p.b*x + p.c
end

Sometimes if a type has many fields, I define a helper function _unpack (or whatever you want to name it) that looks like this:

_unpack(p::Params) = (p.a, p.b, p.c)

And then I could change the implementation of dxdt to be

function dxdt(x, p::Params)
    a, b, c = _unpack(p)
    a*x^2 + b*x + c
end
spencerlyon2
  • 9,476
  • 4
  • 30
  • 39
  • What does this have to do with multiple dispatch? – user4235730 Oct 06 '15 at 17:15
  • In this example nothing, but if you wanted to define a different version of `dxdt` that operated on a different set of parameters you would be all set up to leverage dispatch. I'll amend the first line of the response – spencerlyon2 Oct 06 '15 at 17:40
3

You may use the power of functional language (function as a first-class object and closures):

julia> compose_dxdt = (a,b,c) -> (x) -> a*x^2 + b*x + c #creates function with 3 parameters (a,b,c) which returns the function of x
(anonymous function)

julia> f1 = compose_dxdt(1,1,1) #f1 is a function with the associated values of a=1, b=1, c=1
(anonymous function)

julia> f1(1) 
3

julia> f1(2)
7

julia> f2 = compose_dxdt(2,2,2) #f1 is a function with the associated values of a=2, b=2, c=2
(anonymous function)

julia> f2(1)
6

julia> f2(2)
14
Maciek Leks
  • 1,288
  • 11
  • 21
2

this is a thing:

function dxdt(x, a, b, c)
   a*x^2 + b*x + c
   end

or the compact definition:

dxdt(x, a, b, c) = a*x^2 + b*x + c

see also argument passing in functions in the docs.

npjc
  • 4,134
  • 1
  • 22
  • 34
  • 2
    Thanks for the answer, but I wanted to pass only the variable x, while to have somehow access to a parameter list (I have many parameters to pass, so passing all of them to the function will be a very nasty code). One possible option is to declare global variables, but I understand that Julia will not be able to optimise a code with too many global variables.. – Ohm Oct 06 '15 at 15:39
  • 1
    @Ohm is [this](http://julia.readthedocs.org/en/latest/manual/functions/#keyword-arguments) your use case? – Gnimuc Oct 06 '15 at 16:02
  • @GnimucKey indeed this will help me, but I think I will also try it using type definition, thanks for your tip! – Ohm Oct 06 '15 at 17:01
2

What you want to do really is passing an instance of a data structure (composite data type) to your function. to do this, first design your data type:

type MyType
  x::Vector
  a
  b
  c
end

and implement dxtd function:

function dxdt(val::MyType)
  return val.a*val.x^2 + val.b*val.x + val.c
end

then some where in your code you make an instance of MyType like this:

myinstance = MyType([],0.0,0.0,0.0)

you can update myinstance

myinstance.x = [1.0,2.8,9.0]
myinstance.a = 5

and at the end when myinstance get ready for dxxt

dxdt(myinstance)
Reza Afzalan
  • 5,646
  • 3
  • 26
  • 44
1

To me it sounds like you're looking for anonymous functions. For example:

function dxdt_parametric(x, a, b, c)
   a*x^2 + b*x + c
end

a = 1
b = 2
c = 1

julia> dxdt = x->dxdt_parametric(x, a, b, c)
(anonymous function)

julia> dxdt(3.2)
17.64
tholy
  • 11,882
  • 1
  • 29
  • 42
  • What about a, b and c being global variables? – Davide Oct 07 '15 at 20:02
  • 1
    You can also make them constants, e.g., `dxdt_parametric(x, 1, 2, 1)`. But in general anonymous functions aren't (yet) very efficient. See the FastAnonymous.jl package. – tholy Oct 09 '15 at 01:57