# using a Mathematica function to define a new function

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?

-
A solution like the one to this question might be useful to you. –  episanty Nov 12 '13 at 19:00

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.

-
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! –  user1451632 Nov 12 '13 at 16:43
@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 –  tkott Nov 12 '13 at 17:31
Terrific! This really helps. Thank you for your time. –  user1451632 Nov 12 '13 at 21:27