Defining a Function programmatically
Possibly this:
mon = Unique[NDSolve`Monitor];
mons = Table[Unique[mon], {3}];
vars = {t, x, y};
Block[{Set, Unset, CompoundExpression},
With[{code = CompoundExpression @@ Join[
Unset /@ #3,
MapThread[
Set,
{Prepend[Through[Rest[#3][First[#3]]], First[#3]], #2}],
{#1}
]},
Function @@ {{#1},
Function @@ Hold[#2, Internal`InheritedBlock[#3, code]]}
]] &[mon, mons, vars]
(*
Function[{NDSolve`Monitor$234166},
Function[{NDSolve`Monitor$234166$234167,
NDSolve`Monitor$234166$234168, NDSolve`Monitor$234166$234169},
Internal`InheritedBlock[{t, x, y},
t =.;
x =.;
y =.;
t = NDSolve`Monitor$234166$234167;
x[t] = NDSolve`Monitor$234166$234168;
y[t] = NDSolve`Monitor$234166$234169;
NDSolve`Monitor$234166
]]]
*)
Update:
This avoids blocking system functions. It shouldn't be a problem above because of the limited scope of the Block[]
and the fact that the arguments mon, mons, vars
are all evaluated before injected; but maybe it seems safer the following way.
With[{code = Join[
Hold[#1, #2, #3], (* first args of Function and InheritedBlock *)
Unset /@ Hold @@ #3, (* beginning of body *)
Set @@@ Hold @@ Transpose@
{Prepend[Through[Rest[#3][First[#3]]], First[#3]], #2},
Hold[#1]
]},
Replace[code, Hold[m1_, m2_, v_, body__] :>
Function[{m1}, Function[m2,
Internal`InheritedBlock[v, CompoundExpression[body]]]]]
] &[mon, mons, vars]
(* same output as above *)
ClearAll[makeArgs, makeFunc]
makeArgs[m_, ms_, v_] := {{m}, ms, Inactive[Internal`InheritedBlock][v,
Inactive[CompoundExpression] @@ Flatten[
{Inactive[Unset] /@ v, Inactive[Set][ v[[1]], ms[[1]]],
Inactivate[Thread[Through[Rest[v] @ First[v]] = Rest[ms]], Set], m}]]};
makeFunc = Function[#, Evaluate @ Activate @ Function[#2, #3]] & @@ makeArgs[##] &;
makeFunc[mon, mons, vars]
Function[{NDSolve`Monitor$30945}, Function[{NDSolve`Monitor$30945$30952, NDSolve`Monitor$30945$30953, NDSolve`Monitor$30945$30954}, Internal`InheritedBlock[{t, x, y}, t =.; x =.; y =.; t = NDSolve`Monitor$30945$30952; x[t] = NDSolve`Monitor$30945$30953; y[t] = NDSolve`Monitor$30945$30954; NDSolve`Monitor$30945]]]
Rather than try to figure out what your detailed intentions are, let me just give a simple example. This kind of thing is easy with Function
because it holds its arguments until it is applied. You may thus reach into a Function
and perform arbitrary replacements. There is no need to clumsily edit text. Here, I define powerN
as a prototype, and do replacements:
powerN = Function[{x}, x^n];
power2 = powerN /. n -> 2
(* Function[{x}, x^2] *)
Another way is to define a constructor:
power[n_] := Function[{x}, x^n]
power[2]
(* Function[{x$}, x$^2] *)