# How to compile expression which returns a pure function?

Using Mathematica the definition of user functions , which return "pure functions" is quite easy

f[list_] := Function[t, Sin[list[[1]] t] + list[[2]] Cos[t]]
Plot[f[{2, 1}][t], {t, 0, 2 Pi}]


and often very useful. Please note the use of f[liste][time] with separated argument brackets.

My question: Is it possible to pre-compile the part f[list] in such a way that it returns a pure function object?

here a small example to clarify my question:

pg[a_(*liste *)] := Interpolation[{{0, 0}, {.4, a[[1]]}, {.8, a[[2]]}, {1, 1}} , InterpolationOrder -> 1]


defines a polygon with two variable points. pg[a] is a pure function object which can be used to find the polygon pg[a][x]~=x

opt = NMinimize[Sum[(trapez[{a, b}][x] - x)^2, {x, 0, 1, .2}], {a, b}]

• It is not clear to me why you want to compile the creation of the actual function. Oftentimes, it will be helpful enough to create the function only once, like in f[list_] := Function[t, Evaluate[Sin[list[[1]] t] + list[[2]] Cos[t]]]; g = f[{2, 1}]; Plot[g[t], {t, 0, 2 Pi}] – Henrik Schumacher Sep 7 '18 at 10:59
• Thanks! My intention is to create an approximation function , which depends on a list of paramaters. Something like Interpoaltion[data[parameters]]  These parameters are evaluated in a minimization process(involving NDSOlve,NMinimize), which calls the function repeatedly. For performance issues I would like to try a compiled version. – Ulrich Neumann Sep 7 '18 at 11:16
• Hm. I don't get it. Would you please try to give a more concrete example that emphasizes where the performance bottleneck is? Btw.: Compiled functions cannot return a pure function. And if complex functions such as NMinimize or NDSolve appear in the code, it is usually not a good idea to compile it. But there might be other ways to speed up your code. – Henrik Schumacher Sep 7 '18 at 11:26

Here is simple code to get you going:

Clear[inferType];
inferType[arg_Integer] := _Integer
inferType[arg:_Real | _?NumericQ /; Re[arg]==arg] := _Real
inferType[arg_List] /; ArrayQ[arg,_,IntegerQ]:=
{_Integer,Length[Dimensions[arg]]};
inferType[arg_List] /; ArrayQ[arg,_,NumericQ] && Re[arg]==arg:=
{_Real,Length[Dimensions[arg]]};
inferType[_]:= General;

ClearAll[memoize, compile, $preprocessingRules]$preprocessingRules  = {
p: HoldPattern[Part[list:{__Integer}, part_Integer]] :>
RuleCondition[p]
};

memoize[fn:HoldPattern[Function[var_, body_]], General]:= compile[fn] = fn

memoize[fn:HoldPattern[Function[var_, body_]], {t__} | t__] := compile[fn] =
Replace[
ReplaceAll[Hold[body], \$preprocessingRules],
Hold[preprocessed_] :> Compile[{{var, t}}, preprocessed]
]

compile[fn:HoldPattern[Function[var_, body_]]][arg_]:=
memoize[fn, inferType[arg]][arg]


And then

f[list_]:=compile[Function[t,Sin[list[[1]] t]+list[[2]] Cos[t]]]


and

Plot[f[{2, 1}][t], {t, 0, 2 Pi}]


You can check what function was generated by calling

?compile


Both type-inferencer and preprocessor are very simplistic, and this is for one - argument function only, but this can be a starting point, if you want this kind of things.

• Thank you for your tough answer, I will need a nonpredictable amount of time to understand it.... – Ulrich Neumann Sep 7 '18 at 12:20
• @UlrichNeumann I will try to add some explanations when I get a spare moment. – Leonid Shifrin Sep 7 '18 at 12:55
• Thanks again for your effort!. – Ulrich Neumann Sep 7 '18 at 13:02
• What do you think about this variant Compile[{{list , _Real, 1}}, Function[t, Sin[list[[1]] t] + list[[2]] Cos[t]] &]? What is the difference to your solution? Thanks! – Ulrich Neumann Sep 8 '18 at 20:35
• @UlrichNeumann The difference is that my code gets compiled dynamically, already after list variable value gets injected into Compile. Your suggestion won't work as intended, because Compile can't return a compiled pure function, and so the Function will remain uncompiled. – Leonid Shifrin Sep 9 '18 at 19:16