1
$\begingroup$

I'd like to define a function of three variables which produces a new, named function of a single variable, where this final variable is not a member of the first three. So I'd like something where I have

f0[x_ , y_ , z_] := << complicated function >>

which gives f1[p_]. Furthermore, I'd like to have the functions be defined in such a way that when I write

IN:= f0[x0,y0,z0]

I get

OUT:= fx0y0z0[p_]

so that I can easily identify which inputs produced the function. So, basically, I'd like to wind up with a function produced via Interpolation and I'd like that function to have a specific name defined by my inputs.

For instance, let's say I'm creating a numerical function by writing down a table in two variables (say, p and q) that requires x, y, and z as inputs. Then I'd like to integrate over q and interpolate over p so that my final function is just a function over q only.

So, let's say that my first function is

g[x_,y_,z_,p_,q_] := (x + y + z) p / q

Now I'd like to tabulate this over p and q for given values of x, y, and z. Then I'd like to integrate over p and have a function of q only. I can for instance do the following

f1[x_,y_,z_] := NIntegrate[
  Interpolation[
    Flatten[Table[{q, p, 
       g[x,y,z,p,q]}, {p,p0,p1}, {q,q0,q1}],1]][#,
    p], {p, p0, p1}] &

and then this is a well-behaved function of q which I can make tables of, which I can then plot, integrate, etc. just by writing f1[x0,y0,x0][q]. But this is not very convenient for me since it requires me to write out a new function name every time I want to examine the behavior as a function of different values of x, y, and z, and I will ultimately need many values of x, y, and z. Is there any way to write a meta-function that is capable of producing a brand new interpolating function of q only, with the name including the input values of x, y, and z?

$\endgroup$
1

1 Answer 1

1
$\begingroup$

I typically use pure functions for this type of meta programming. For example:

generator[p_,q_] := Function[{x,y,z},
  Evaluate[ 
    Integrate[ (x+y+z)/(p+q), {p,p0,p1},{q,q0,q1}]
  ]
]

Then one can use it as

fpXqY = generator[X,Y]

And then fpXqY will be a pure function you can use. This only works for function that can be treated as pure functions. However, one can also do something similar by just calling SetDelayed[] (which is the full form of :=) within your generator to create a new function. So something like:

generator2[p_,q_] := SetDelayed[ 
  ToExpression[ StringJoin[ "fp", ToString[p], "q", ToString[q]]][x_, y_, z_]
  , Integrate[ (x+y+z)/(p+q), {p,p0,p1},{q,q0,q1}]
]

And then call it as

generator2[X,Y]

and you should then find you can use fpXqY as your evaluator. Note that you can either use Set or SetDelayed as you need.

$\endgroup$
3
  • $\begingroup$ Thanks -- this seems to be on the right track. However, my goal is to produce a function with an entirely new name. Say I have g[x_,y_,z_,p_,q_]:=(x+y+z)p/q f1[x_,y_,z_] := NIntegrate[Interpolation[Flatten[Table[{q,p,g[x,y,z,p,q]},{p,10}, {q,10}],1]][#,p],{p,1,10}]& as before. What is wrong with the following? generator[x_,y_,z_]:=SetDelayed[ToExpression[ToString[StringForm["f1``````",x,y,z]]][#]&,Interpolation[Table[f1[x,y,z][p],{p,10}]]] I'd like to produce, e.g., f1323 = Interpolation[Table[f1[3,2,3][x],{x,10}]]; which is easily identifiable and very fast. Thank you for your help! $\endgroup$ Nov 12, 2013 at 16:43
  • $\begingroup$ @user1451632 right sorry, let me fix that -- see the updated generator 2. In general, you should avoid using StringForm for producing function names -- the *Form sometimes introduces odd quirks $\endgroup$
    – tkott
    Nov 12, 2013 at 17:31
  • $\begingroup$ Terrific! This really helps. Thank you for your time. $\endgroup$ Nov 12, 2013 at 21:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.