# How do I make function A create and return function B?

My basic need is I have to take lots of data and other information and assemble it into a function (static parameters). I then need to call the function many times for numerical results for many values of the dynamic parameters. I then need to repeat with a new set of static parameters. I have a workable solution that I'm using now but it does not feel like a slick solution. So I'm looking for some fresh ideas.

MakeRegion[id_, g_, geo_] := (
listend = #[[-1]] & /@ (Select[
FindShortestPath[g, id, #] & /@ (Pick[VertexList[g],
VertexOutDegree[g], 0]), Length[#] > 0 &]);
cond = Table[
{crf, rrf, typerf, ptsrf} = {ApCenter, ApR, Type, ApPoints} /. geo[[listend[[i]]]];
Which[
typerf == "Polygon", PointInPoly[ptsrf, {x, y}],
typerf == "Circle", (x - crf[])^2 + (y - crf[])^2 <= r
],
{i, 1, Length[listend]}];
Clear[region];
region[x_, y_] := Evaluate[Or @@ cond];
);


I do not think I need to go into the details of the code for you to get the idea. MakeRegion takes in geometry information and creates the function region[x,y] which is a logical domain that I can use in NIntegrate and other functions.

Here is a simple example:

Clear[example]
example[a_] := (
Clear[fun];
fun[x_, y_] :=
Evaluate[x Total[RandomVariate[NormalDistribution[], a]] + y ];
);


The function example has no return value, but it defines the function fun, which I can use until I need to get a new instance of the function fun which I do by running example[a].

• your function MakeRegion can't work : It doesn't return anything because of the semi-colon at the end of the last but one line – andre314 Feb 23 '13 at 12:53
• Yes the function MakeRegion does not have a return value but it does define the function region which is the function that I use for the numerical calculations. Here is a simple proof of concept example: Clear[example] example[a_] := ( Clear[fun]; fun[x_, y_] := Evaluate[x Total[RandomVariate[NormalDistribution[], a]] + y ]; ); – c186282 Feb 23 '13 at 13:14
• Here are two links to posts using closures. You might find these interesting. 1 and 2 – Szabolcs Feb 24 '13 at 21:09

## 2 Answers

The more Mathematica-like way of doing this is to actually return a function, rather than define a single global function as a side-effect:

createFunction[a_] :=
Function[{x,y},
x Total[RandomVariate[NormalDistribution[], a]] + y
]


Now you can create as many functions parameterized by a as you like, assign those functions, pass them other places:

f3=createFunction
f9=createFunction
{NIntegrate[f3[x, y], {x, 0, 5}, {y, 0, 4}]], Plot[f9[x, 5.], {x, 0, 5}]}

• Thank you. I had originally tried something like this but I made the silly mistake of doing f3:=createFunction. Note, improper usage of := – c186282 Feb 23 '13 at 17:42

Over the years I have come across more situations where I need Function A to create function B. I have used what was provided by "Joel Klein" but I wanted more and I have come across a better way to get done what I need:

Clear[AmakeB];

Options[AmakeB] = {"FunctionName" -> Automatic, "Quiet" -> False};

AmakeB::Function = "I made your function 1";

AmakeB[a_, b_, opts : OptionsPattern[AmakeB]] := Module[
{fn},
fn = OptionValue["FunctionName"];
If[! StringQ[fn], fn = "Fun"];

Clear[Evaluate[Symbol[fn]]];
With[{av = a, bv = b},
Evaluate[Symbol[fn]][x_?NumericQ] := av Cos[bv x];
Evaluate[Symbol[fn]]["Info"] = <|"a" -> av, "b" -> bv|>
];
If[! TrueQ[OptionValue["Quiet"]],
Message[AmakeB::Function, fn]
];

]


Now the function that is created is not returned via a Return from the Module but is added to the Global context. One of the advantages to me is that now I can define an arbitrarily complex function.

Usage:

AmakeB[1, 1]


Returns nothing but now the function Fun exists:

?Fun
(*
GlobalFun
Fun[Info]=<|a->1,b->1|>
Fun[x$_?NumericQ]:=1 Cos[1 x$]
*)


Make another function:

AmakeB[1, 2, "FunctionName" -> "Yes"]


Now the function Yes exists

?Yes
(*
Yes[Info]=<|a->1,b->2|>

Yes[x$_?NumericQ]:=1 Cos[2 x$]
*)
`