Defining a Function programmaticallyExamine function parameters programmaticallyReplace function call with expression resulting from the symbolic evaluation of the function when defining a second function?using a Mathematica function to define a new functionHow to programmatically covert a function-like rule to a pure function?Add semicolon at the end of code line programmaticallyTable with programmatically specified number of iterators in CompileMeta information about function parametersFull memory from defining a single functionMathematica function which formats Physics calculationEfficiently defining a SparseArray function
Old French song lyrics with the word "baiser."
Trapped in an ocean Temple in Minecraft?
If Trump gets impeached, how long would Pence be president?
Converting 8V AC to 8V DC - bridge rectifier gets very hot while idling
How did the Axis intend to hold the Caucasus?
(2 of 11: Moon-or-Sun) What is Pyramid Cult's Favorite Camera?
How can I rectify up to 85 kV
Heisenberg uncertainty principle in daily life
How much were the LMs maneuvered to their landing points?
What is the difference between 1/3, 1/2, and full casters?
How to store my pliers and wire cutters on my desk?
Why isn't there any 9.5 digit multimeter or higher?
Why force the nose of 737 Max down in the first place?
Is a topological space considered to be a class in set theory?
Request for a Latin phrase as motto "God is highest/supreme"
Did the IBM PC use the 8088's NMI line?
Which approach can I use to generate text based on multiple inputs?
Writing a clean implementation of rock–paper–scissors game in C++
Why didn't Britain or any other European power colonise Abyssinia/Ethiopia before 1936?
The Sword in the Stone
Is there an antonym for "spicy" or "hot" regarding food (NOT "seasoned" but "spicy")?
Why isn't there a serious attempt at creating a third mass-appeal party in the US?
Could the rotation of a black hole cause other planets to rotate?
May a man marry the women with whom he committed adultery?
Defining a Function programmatically
Examine function parameters programmaticallyReplace function call with expression resulting from the symbolic evaluation of the function when defining a second function?using a Mathematica function to define a new functionHow to programmatically covert a function-like rule to a pure function?Add semicolon at the end of code line programmaticallyTable with programmatically specified number of iterators in CompileMeta information about function parametersFull memory from defining a single functionMathematica function which formats Physics calculationEfficiently defining a SparseArray function
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
$begingroup$
I need to create a function programmatically. For example, suppose I've got:
- mon - a Symbol
- mons - a List of Symbols
- vars - another List of Symbols (same Length)
and want to make a function as:
Function[«mon»,
Function[«mons»,
Internal`InheritedBlock[«vars»,
«vars[[1]]» =.;
«vars[[2]]» =.;
...
«vars[[-1]]» =.;
«vars[[1]]» = «mons[[1]]»;
«vars[[2]]»[t] = «mons[[2]]»;
...
«vars[[-1]]»[t] = «mons[[-1]]»;
«mon»
]]]
where «» denotes injecting from the given mon, mons, and vars.
So the input
mon = Unique[NDSolve`Monitor];
mons = Table[Unique[mon], 3];
vars = t, x, y;
would result in the desired output:
Function[NDSolve`Monitor$3080,
Function[NDSolve`Monitor$3080$3081, NDSolve`Monitor$3080$3082, NDSolve`Monitor$3080$3083,
Internal`InheritedBlock[t, x, y,
t =.;
x =.;
y =.;
t = NDSolve`Monitor$3080$3081;
x[t] = NDSolve`Monitor$3080$3082;
y[t] = NDSolve`Monitor$3080$3083;
NDSolve`Monitor$3080
]]]
One possible solution involves building up a String
, then using ToExpression
:
str = "Function[" <> ToString[mon] <> ",
Function[" <> ToString[mons] <> ",
Internal`InheritedBlock[" <> ToString[vars] <> ",
";
Do[
str = str <> ToString[var] <> "=.;n"
, var, vars];
str = str <> "t=" <> ToString[mons[[1]]] <> ";n";
Do[
str = str <> ToString[vars[[i]]] <> "[t]=" <> ToString[mons[[i]]] <> ";n"
, i, 2, Length[vars]];
str = str <> ToString[mon] <> "]]]n";
but this is kind of inelegant and can be slow for large lists.
Are there any nicer and/or faster alternatives?
performance-tuning meta-programming
$endgroup$
|
show 1 more comment
$begingroup$
I need to create a function programmatically. For example, suppose I've got:
- mon - a Symbol
- mons - a List of Symbols
- vars - another List of Symbols (same Length)
and want to make a function as:
Function[«mon»,
Function[«mons»,
Internal`InheritedBlock[«vars»,
«vars[[1]]» =.;
«vars[[2]]» =.;
...
«vars[[-1]]» =.;
«vars[[1]]» = «mons[[1]]»;
«vars[[2]]»[t] = «mons[[2]]»;
...
«vars[[-1]]»[t] = «mons[[-1]]»;
«mon»
]]]
where «» denotes injecting from the given mon, mons, and vars.
So the input
mon = Unique[NDSolve`Monitor];
mons = Table[Unique[mon], 3];
vars = t, x, y;
would result in the desired output:
Function[NDSolve`Monitor$3080,
Function[NDSolve`Monitor$3080$3081, NDSolve`Monitor$3080$3082, NDSolve`Monitor$3080$3083,
Internal`InheritedBlock[t, x, y,
t =.;
x =.;
y =.;
t = NDSolve`Monitor$3080$3081;
x[t] = NDSolve`Monitor$3080$3082;
y[t] = NDSolve`Monitor$3080$3083;
NDSolve`Monitor$3080
]]]
One possible solution involves building up a String
, then using ToExpression
:
str = "Function[" <> ToString[mon] <> ",
Function[" <> ToString[mons] <> ",
Internal`InheritedBlock[" <> ToString[vars] <> ",
";
Do[
str = str <> ToString[var] <> "=.;n"
, var, vars];
str = str <> "t=" <> ToString[mons[[1]]] <> ";n";
Do[
str = str <> ToString[vars[[i]]] <> "[t]=" <> ToString[mons[[i]]] <> ";n"
, i, 2, Length[vars]];
str = str <> ToString[mon] <> "]]]n";
but this is kind of inelegant and can be slow for large lists.
Are there any nicer and/or faster alternatives?
performance-tuning meta-programming
$endgroup$
$begingroup$
Sorry, it is not at all clear to me what you try to achieve. Would you please give a concrete example?
$endgroup$
– Henrik Schumacher
9 hours ago
$begingroup$
@HenrikSchumacher I want to make the third code block based on the info given in the second code block. The code following “One possible solution...” does what I want, but it’s slow.
$endgroup$
– Chris K
9 hours ago
1
$begingroup$
Uuuh... Do you really want to have such a side effect in a pure function? Yes, Mathematica allows you to do that by I would not consider it programming practice.
$endgroup$
– Henrik Schumacher
9 hours ago
2
$begingroup$
It might be worth mentioning that you need this for a specific purpose (working with theStateData
internals) such that it must be a pure function like this.
$endgroup$
– b3m2a1
8 hours ago
1
$begingroup$
As @b3m2a1 alludes to, I do have a specific reason to achieve what I asked for. Maybe there's an easier way, but I thought it would be better to ask this question on its own rather than mixed in with that complicated project. Anyhow, I'll link to the Q&A that motivates this question as soon as I write it up.
$endgroup$
– Chris K
8 hours ago
|
show 1 more comment
$begingroup$
I need to create a function programmatically. For example, suppose I've got:
- mon - a Symbol
- mons - a List of Symbols
- vars - another List of Symbols (same Length)
and want to make a function as:
Function[«mon»,
Function[«mons»,
Internal`InheritedBlock[«vars»,
«vars[[1]]» =.;
«vars[[2]]» =.;
...
«vars[[-1]]» =.;
«vars[[1]]» = «mons[[1]]»;
«vars[[2]]»[t] = «mons[[2]]»;
...
«vars[[-1]]»[t] = «mons[[-1]]»;
«mon»
]]]
where «» denotes injecting from the given mon, mons, and vars.
So the input
mon = Unique[NDSolve`Monitor];
mons = Table[Unique[mon], 3];
vars = t, x, y;
would result in the desired output:
Function[NDSolve`Monitor$3080,
Function[NDSolve`Monitor$3080$3081, NDSolve`Monitor$3080$3082, NDSolve`Monitor$3080$3083,
Internal`InheritedBlock[t, x, y,
t =.;
x =.;
y =.;
t = NDSolve`Monitor$3080$3081;
x[t] = NDSolve`Monitor$3080$3082;
y[t] = NDSolve`Monitor$3080$3083;
NDSolve`Monitor$3080
]]]
One possible solution involves building up a String
, then using ToExpression
:
str = "Function[" <> ToString[mon] <> ",
Function[" <> ToString[mons] <> ",
Internal`InheritedBlock[" <> ToString[vars] <> ",
";
Do[
str = str <> ToString[var] <> "=.;n"
, var, vars];
str = str <> "t=" <> ToString[mons[[1]]] <> ";n";
Do[
str = str <> ToString[vars[[i]]] <> "[t]=" <> ToString[mons[[i]]] <> ";n"
, i, 2, Length[vars]];
str = str <> ToString[mon] <> "]]]n";
but this is kind of inelegant and can be slow for large lists.
Are there any nicer and/or faster alternatives?
performance-tuning meta-programming
$endgroup$
I need to create a function programmatically. For example, suppose I've got:
- mon - a Symbol
- mons - a List of Symbols
- vars - another List of Symbols (same Length)
and want to make a function as:
Function[«mon»,
Function[«mons»,
Internal`InheritedBlock[«vars»,
«vars[[1]]» =.;
«vars[[2]]» =.;
...
«vars[[-1]]» =.;
«vars[[1]]» = «mons[[1]]»;
«vars[[2]]»[t] = «mons[[2]]»;
...
«vars[[-1]]»[t] = «mons[[-1]]»;
«mon»
]]]
where «» denotes injecting from the given mon, mons, and vars.
So the input
mon = Unique[NDSolve`Monitor];
mons = Table[Unique[mon], 3];
vars = t, x, y;
would result in the desired output:
Function[NDSolve`Monitor$3080,
Function[NDSolve`Monitor$3080$3081, NDSolve`Monitor$3080$3082, NDSolve`Monitor$3080$3083,
Internal`InheritedBlock[t, x, y,
t =.;
x =.;
y =.;
t = NDSolve`Monitor$3080$3081;
x[t] = NDSolve`Monitor$3080$3082;
y[t] = NDSolve`Monitor$3080$3083;
NDSolve`Monitor$3080
]]]
One possible solution involves building up a String
, then using ToExpression
:
str = "Function[" <> ToString[mon] <> ",
Function[" <> ToString[mons] <> ",
Internal`InheritedBlock[" <> ToString[vars] <> ",
";
Do[
str = str <> ToString[var] <> "=.;n"
, var, vars];
str = str <> "t=" <> ToString[mons[[1]]] <> ";n";
Do[
str = str <> ToString[vars[[i]]] <> "[t]=" <> ToString[mons[[i]]] <> ";n"
, i, 2, Length[vars]];
str = str <> ToString[mon] <> "]]]n";
but this is kind of inelegant and can be slow for large lists.
Are there any nicer and/or faster alternatives?
performance-tuning meta-programming
performance-tuning meta-programming
edited 9 hours ago
Chris K
asked 10 hours ago
Chris KChris K
9,2202 gold badges23 silver badges50 bronze badges
9,2202 gold badges23 silver badges50 bronze badges
$begingroup$
Sorry, it is not at all clear to me what you try to achieve. Would you please give a concrete example?
$endgroup$
– Henrik Schumacher
9 hours ago
$begingroup$
@HenrikSchumacher I want to make the third code block based on the info given in the second code block. The code following “One possible solution...” does what I want, but it’s slow.
$endgroup$
– Chris K
9 hours ago
1
$begingroup$
Uuuh... Do you really want to have such a side effect in a pure function? Yes, Mathematica allows you to do that by I would not consider it programming practice.
$endgroup$
– Henrik Schumacher
9 hours ago
2
$begingroup$
It might be worth mentioning that you need this for a specific purpose (working with theStateData
internals) such that it must be a pure function like this.
$endgroup$
– b3m2a1
8 hours ago
1
$begingroup$
As @b3m2a1 alludes to, I do have a specific reason to achieve what I asked for. Maybe there's an easier way, but I thought it would be better to ask this question on its own rather than mixed in with that complicated project. Anyhow, I'll link to the Q&A that motivates this question as soon as I write it up.
$endgroup$
– Chris K
8 hours ago
|
show 1 more comment
$begingroup$
Sorry, it is not at all clear to me what you try to achieve. Would you please give a concrete example?
$endgroup$
– Henrik Schumacher
9 hours ago
$begingroup$
@HenrikSchumacher I want to make the third code block based on the info given in the second code block. The code following “One possible solution...” does what I want, but it’s slow.
$endgroup$
– Chris K
9 hours ago
1
$begingroup$
Uuuh... Do you really want to have such a side effect in a pure function? Yes, Mathematica allows you to do that by I would not consider it programming practice.
$endgroup$
– Henrik Schumacher
9 hours ago
2
$begingroup$
It might be worth mentioning that you need this for a specific purpose (working with theStateData
internals) such that it must be a pure function like this.
$endgroup$
– b3m2a1
8 hours ago
1
$begingroup$
As @b3m2a1 alludes to, I do have a specific reason to achieve what I asked for. Maybe there's an easier way, but I thought it would be better to ask this question on its own rather than mixed in with that complicated project. Anyhow, I'll link to the Q&A that motivates this question as soon as I write it up.
$endgroup$
– Chris K
8 hours ago
$begingroup$
Sorry, it is not at all clear to me what you try to achieve. Would you please give a concrete example?
$endgroup$
– Henrik Schumacher
9 hours ago
$begingroup$
Sorry, it is not at all clear to me what you try to achieve. Would you please give a concrete example?
$endgroup$
– Henrik Schumacher
9 hours ago
$begingroup$
@HenrikSchumacher I want to make the third code block based on the info given in the second code block. The code following “One possible solution...” does what I want, but it’s slow.
$endgroup$
– Chris K
9 hours ago
$begingroup$
@HenrikSchumacher I want to make the third code block based on the info given in the second code block. The code following “One possible solution...” does what I want, but it’s slow.
$endgroup$
– Chris K
9 hours ago
1
1
$begingroup$
Uuuh... Do you really want to have such a side effect in a pure function? Yes, Mathematica allows you to do that by I would not consider it programming practice.
$endgroup$
– Henrik Schumacher
9 hours ago
$begingroup$
Uuuh... Do you really want to have such a side effect in a pure function? Yes, Mathematica allows you to do that by I would not consider it programming practice.
$endgroup$
– Henrik Schumacher
9 hours ago
2
2
$begingroup$
It might be worth mentioning that you need this for a specific purpose (working with the
StateData
internals) such that it must be a pure function like this.$endgroup$
– b3m2a1
8 hours ago
$begingroup$
It might be worth mentioning that you need this for a specific purpose (working with the
StateData
internals) such that it must be a pure function like this.$endgroup$
– b3m2a1
8 hours ago
1
1
$begingroup$
As @b3m2a1 alludes to, I do have a specific reason to achieve what I asked for. Maybe there's an easier way, but I thought it would be better to ask this question on its own rather than mixed in with that complicated project. Anyhow, I'll link to the Q&A that motivates this question as soon as I write it up.
$endgroup$
– Chris K
8 hours ago
$begingroup$
As @b3m2a1 alludes to, I do have a specific reason to achieve what I asked for. Maybe there's an easier way, but I thought it would be better to ask this question on its own rather than mixed in with that complicated project. Anyhow, I'll link to the Q&A that motivates this question as soon as I write it up.
$endgroup$
– Chris K
8 hours ago
|
show 1 more comment
4 Answers
4
active
oldest
votes
$begingroup$
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 *)
$endgroup$
1
$begingroup$
@kglr Tee-hee, how funny....Touché, as they say. Thanks! I've got several versions. I guess copied the wrong one.
$endgroup$
– Michael E2
4 hours ago
$begingroup$
AlsoBlock[Set, Unset, CompoundExpression, Function[#1, Function[#2, Internal`InheritedBlock[#3, #4]]] &[ mon, mons, vars, CompoundExpression @@ Join[ Unset /@ vars, MapThread[Set, Prepend[Through[Rest[vars]@First[vars]], First[vars]], mons], mon] ] ]
$endgroup$
– Michael E2
3 hours ago
add a comment |
$begingroup$
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]]]
$endgroup$
add a comment |
$begingroup$
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] *)
$endgroup$
$begingroup$
I think injecting the variable bits into theInternal`InheritedBlock
is more my problem, but thanks.
$endgroup$
– Chris K
8 hours ago
add a comment |
$begingroup$
Is there any reason why this won't work?
doopDoopDoop~SetAttributes~HoldAll;
doopDoopDoop[
mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol,
body1_,
body2_
] :=
Function[mon,
Function[mons,
Internal`InheritedBlock[vars,
vars[[1]] =.;
vars[[2]] =.;
body1;
vars[[-1]] =.;
vars[[1]] vars = mons[[1]] mons;
vars[[2]][t] = mons[[2]];
body2;
vars[[-1]][t] = mons[[-1]];
mon
]
]
]
Then:
doopDoopDoop[
a, b, c, d, e, t,
1,
2
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
The annoying thing will be the parameter injection if you have mons
stored as a list. In this case I'm going to assume you have each variable wrapped in Hold
, because that makes it a bit more subtle. The way we'll prep the parameter list is then:
depVar = Hold@a;
mons = Thread@Hold@b, c;
vars = Thread@Hold@d, e;
timeVar = Hold@t;
paramList =
Thread[depVar, Thread[mons, Hold], Thread[vars, Hold], timeVar, Hold]
Hold[a, b, c, d, e, t]
Then we inject it like:
Replace[
paramList,
Hold[pars_] :>
doopDoopDoop[
pars,
1,
2
]
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
In general, the final thing you'll want to do with an injection is wrap it in a Replace
to inject the contents of the Hold
or provide a function with DownValues
that does the injection, e.g.:
doopDoopDoopHold~SetAttributes~HoldRest;
doopDoopDoopHold[
Hold[pars : mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol],
body1_,
body2_
] :=
doopDoopDoop[pars, body1, body2];
doopDoopDoopHold[paramList, 1, 2]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
$endgroup$
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "387"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f202884%2fdefining-a-function-programmatically%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
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 *)
$endgroup$
1
$begingroup$
@kglr Tee-hee, how funny....Touché, as they say. Thanks! I've got several versions. I guess copied the wrong one.
$endgroup$
– Michael E2
4 hours ago
$begingroup$
AlsoBlock[Set, Unset, CompoundExpression, Function[#1, Function[#2, Internal`InheritedBlock[#3, #4]]] &[ mon, mons, vars, CompoundExpression @@ Join[ Unset /@ vars, MapThread[Set, Prepend[Through[Rest[vars]@First[vars]], First[vars]], mons], mon] ] ]
$endgroup$
– Michael E2
3 hours ago
add a comment |
$begingroup$
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 *)
$endgroup$
1
$begingroup$
@kglr Tee-hee, how funny....Touché, as they say. Thanks! I've got several versions. I guess copied the wrong one.
$endgroup$
– Michael E2
4 hours ago
$begingroup$
AlsoBlock[Set, Unset, CompoundExpression, Function[#1, Function[#2, Internal`InheritedBlock[#3, #4]]] &[ mon, mons, vars, CompoundExpression @@ Join[ Unset /@ vars, MapThread[Set, Prepend[Through[Rest[vars]@First[vars]], First[vars]], mons], mon] ] ]
$endgroup$
– Michael E2
3 hours ago
add a comment |
$begingroup$
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 *)
$endgroup$
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 *)
edited 4 hours ago
answered 8 hours ago
Michael E2Michael E2
156k13 gold badges215 silver badges509 bronze badges
156k13 gold badges215 silver badges509 bronze badges
1
$begingroup$
@kglr Tee-hee, how funny....Touché, as they say. Thanks! I've got several versions. I guess copied the wrong one.
$endgroup$
– Michael E2
4 hours ago
$begingroup$
AlsoBlock[Set, Unset, CompoundExpression, Function[#1, Function[#2, Internal`InheritedBlock[#3, #4]]] &[ mon, mons, vars, CompoundExpression @@ Join[ Unset /@ vars, MapThread[Set, Prepend[Through[Rest[vars]@First[vars]], First[vars]], mons], mon] ] ]
$endgroup$
– Michael E2
3 hours ago
add a comment |
1
$begingroup$
@kglr Tee-hee, how funny....Touché, as they say. Thanks! I've got several versions. I guess copied the wrong one.
$endgroup$
– Michael E2
4 hours ago
$begingroup$
AlsoBlock[Set, Unset, CompoundExpression, Function[#1, Function[#2, Internal`InheritedBlock[#3, #4]]] &[ mon, mons, vars, CompoundExpression @@ Join[ Unset /@ vars, MapThread[Set, Prepend[Through[Rest[vars]@First[vars]], First[vars]], mons], mon] ] ]
$endgroup$
– Michael E2
3 hours ago
1
1
$begingroup$
@kglr Tee-hee, how funny....Touché, as they say. Thanks! I've got several versions. I guess copied the wrong one.
$endgroup$
– Michael E2
4 hours ago
$begingroup$
@kglr Tee-hee, how funny....Touché, as they say. Thanks! I've got several versions. I guess copied the wrong one.
$endgroup$
– Michael E2
4 hours ago
$begingroup$
Also
Block[Set, Unset, CompoundExpression, Function[#1, Function[#2, Internal`InheritedBlock[#3, #4]]] &[ mon, mons, vars, CompoundExpression @@ Join[ Unset /@ vars, MapThread[Set, Prepend[Through[Rest[vars]@First[vars]], First[vars]], mons], mon] ] ]
$endgroup$
– Michael E2
3 hours ago
$begingroup$
Also
Block[Set, Unset, CompoundExpression, Function[#1, Function[#2, Internal`InheritedBlock[#3, #4]]] &[ mon, mons, vars, CompoundExpression @@ Join[ Unset /@ vars, MapThread[Set, Prepend[Through[Rest[vars]@First[vars]], First[vars]], mons], mon] ] ]
$endgroup$
– Michael E2
3 hours ago
add a comment |
$begingroup$
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]]]
$endgroup$
add a comment |
$begingroup$
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]]]
$endgroup$
add a comment |
$begingroup$
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]]]
$endgroup$
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]]]
edited 7 hours ago
answered 7 hours ago
kglrkglr
207k10 gold badges237 silver badges470 bronze badges
207k10 gold badges237 silver badges470 bronze badges
add a comment |
add a comment |
$begingroup$
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] *)
$endgroup$
$begingroup$
I think injecting the variable bits into theInternal`InheritedBlock
is more my problem, but thanks.
$endgroup$
– Chris K
8 hours ago
add a comment |
$begingroup$
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] *)
$endgroup$
$begingroup$
I think injecting the variable bits into theInternal`InheritedBlock
is more my problem, but thanks.
$endgroup$
– Chris K
8 hours ago
add a comment |
$begingroup$
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] *)
$endgroup$
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] *)
answered 8 hours ago
John DotyJohn Doty
8,4331 gold badge13 silver badges25 bronze badges
8,4331 gold badge13 silver badges25 bronze badges
$begingroup$
I think injecting the variable bits into theInternal`InheritedBlock
is more my problem, but thanks.
$endgroup$
– Chris K
8 hours ago
add a comment |
$begingroup$
I think injecting the variable bits into theInternal`InheritedBlock
is more my problem, but thanks.
$endgroup$
– Chris K
8 hours ago
$begingroup$
I think injecting the variable bits into the
Internal`InheritedBlock
is more my problem, but thanks.$endgroup$
– Chris K
8 hours ago
$begingroup$
I think injecting the variable bits into the
Internal`InheritedBlock
is more my problem, but thanks.$endgroup$
– Chris K
8 hours ago
add a comment |
$begingroup$
Is there any reason why this won't work?
doopDoopDoop~SetAttributes~HoldAll;
doopDoopDoop[
mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol,
body1_,
body2_
] :=
Function[mon,
Function[mons,
Internal`InheritedBlock[vars,
vars[[1]] =.;
vars[[2]] =.;
body1;
vars[[-1]] =.;
vars[[1]] vars = mons[[1]] mons;
vars[[2]][t] = mons[[2]];
body2;
vars[[-1]][t] = mons[[-1]];
mon
]
]
]
Then:
doopDoopDoop[
a, b, c, d, e, t,
1,
2
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
The annoying thing will be the parameter injection if you have mons
stored as a list. In this case I'm going to assume you have each variable wrapped in Hold
, because that makes it a bit more subtle. The way we'll prep the parameter list is then:
depVar = Hold@a;
mons = Thread@Hold@b, c;
vars = Thread@Hold@d, e;
timeVar = Hold@t;
paramList =
Thread[depVar, Thread[mons, Hold], Thread[vars, Hold], timeVar, Hold]
Hold[a, b, c, d, e, t]
Then we inject it like:
Replace[
paramList,
Hold[pars_] :>
doopDoopDoop[
pars,
1,
2
]
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
In general, the final thing you'll want to do with an injection is wrap it in a Replace
to inject the contents of the Hold
or provide a function with DownValues
that does the injection, e.g.:
doopDoopDoopHold~SetAttributes~HoldRest;
doopDoopDoopHold[
Hold[pars : mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol],
body1_,
body2_
] :=
doopDoopDoop[pars, body1, body2];
doopDoopDoopHold[paramList, 1, 2]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
$endgroup$
add a comment |
$begingroup$
Is there any reason why this won't work?
doopDoopDoop~SetAttributes~HoldAll;
doopDoopDoop[
mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol,
body1_,
body2_
] :=
Function[mon,
Function[mons,
Internal`InheritedBlock[vars,
vars[[1]] =.;
vars[[2]] =.;
body1;
vars[[-1]] =.;
vars[[1]] vars = mons[[1]] mons;
vars[[2]][t] = mons[[2]];
body2;
vars[[-1]][t] = mons[[-1]];
mon
]
]
]
Then:
doopDoopDoop[
a, b, c, d, e, t,
1,
2
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
The annoying thing will be the parameter injection if you have mons
stored as a list. In this case I'm going to assume you have each variable wrapped in Hold
, because that makes it a bit more subtle. The way we'll prep the parameter list is then:
depVar = Hold@a;
mons = Thread@Hold@b, c;
vars = Thread@Hold@d, e;
timeVar = Hold@t;
paramList =
Thread[depVar, Thread[mons, Hold], Thread[vars, Hold], timeVar, Hold]
Hold[a, b, c, d, e, t]
Then we inject it like:
Replace[
paramList,
Hold[pars_] :>
doopDoopDoop[
pars,
1,
2
]
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
In general, the final thing you'll want to do with an injection is wrap it in a Replace
to inject the contents of the Hold
or provide a function with DownValues
that does the injection, e.g.:
doopDoopDoopHold~SetAttributes~HoldRest;
doopDoopDoopHold[
Hold[pars : mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol],
body1_,
body2_
] :=
doopDoopDoop[pars, body1, body2];
doopDoopDoopHold[paramList, 1, 2]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
$endgroup$
add a comment |
$begingroup$
Is there any reason why this won't work?
doopDoopDoop~SetAttributes~HoldAll;
doopDoopDoop[
mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol,
body1_,
body2_
] :=
Function[mon,
Function[mons,
Internal`InheritedBlock[vars,
vars[[1]] =.;
vars[[2]] =.;
body1;
vars[[-1]] =.;
vars[[1]] vars = mons[[1]] mons;
vars[[2]][t] = mons[[2]];
body2;
vars[[-1]][t] = mons[[-1]];
mon
]
]
]
Then:
doopDoopDoop[
a, b, c, d, e, t,
1,
2
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
The annoying thing will be the parameter injection if you have mons
stored as a list. In this case I'm going to assume you have each variable wrapped in Hold
, because that makes it a bit more subtle. The way we'll prep the parameter list is then:
depVar = Hold@a;
mons = Thread@Hold@b, c;
vars = Thread@Hold@d, e;
timeVar = Hold@t;
paramList =
Thread[depVar, Thread[mons, Hold], Thread[vars, Hold], timeVar, Hold]
Hold[a, b, c, d, e, t]
Then we inject it like:
Replace[
paramList,
Hold[pars_] :>
doopDoopDoop[
pars,
1,
2
]
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
In general, the final thing you'll want to do with an injection is wrap it in a Replace
to inject the contents of the Hold
or provide a function with DownValues
that does the injection, e.g.:
doopDoopDoopHold~SetAttributes~HoldRest;
doopDoopDoopHold[
Hold[pars : mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol],
body1_,
body2_
] :=
doopDoopDoop[pars, body1, body2];
doopDoopDoopHold[paramList, 1, 2]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
$endgroup$
Is there any reason why this won't work?
doopDoopDoop~SetAttributes~HoldAll;
doopDoopDoop[
mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol,
body1_,
body2_
] :=
Function[mon,
Function[mons,
Internal`InheritedBlock[vars,
vars[[1]] =.;
vars[[2]] =.;
body1;
vars[[-1]] =.;
vars[[1]] vars = mons[[1]] mons;
vars[[2]][t] = mons[[2]];
body2;
vars[[-1]][t] = mons[[-1]];
mon
]
]
]
Then:
doopDoopDoop[
a, b, c, d, e, t,
1,
2
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
The annoying thing will be the parameter injection if you have mons
stored as a list. In this case I'm going to assume you have each variable wrapped in Hold
, because that makes it a bit more subtle. The way we'll prep the parameter list is then:
depVar = Hold@a;
mons = Thread@Hold@b, c;
vars = Thread@Hold@d, e;
timeVar = Hold@t;
paramList =
Thread[depVar, Thread[mons, Hold], Thread[vars, Hold], timeVar, Hold]
Hold[a, b, c, d, e, t]
Then we inject it like:
Replace[
paramList,
Hold[pars_] :>
doopDoopDoop[
pars,
1,
2
]
]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
In general, the final thing you'll want to do with an injection is wrap it in a Replace
to inject the contents of the Hold
or provide a function with DownValues
that does the injection, e.g.:
doopDoopDoopHold~SetAttributes~HoldRest;
doopDoopDoopHold[
Hold[pars : mon_Symbol, mons : __Symbol, vars : __Symbol, t_Symbol],
body1_,
body2_
] :=
doopDoopDoop[pars, body1, body2];
doopDoopDoopHold[paramList, 1, 2]
Function[a,
Function[b, c,
Internal`InheritedBlock[d, e, (d, e[[1]]) =.; (d, e[[2]]) =.;
1; (d, e[[-1]]) =.; d, e[[1]] d, e = b, c[[1]] b, c; d, e[[2]][
t] = b, c[[2]]; 2; d, e[[-1]][t] = b, c[[-1]]; a]]]
answered 8 hours ago
b3m2a1b3m2a1
31.2k3 gold badges62 silver badges183 bronze badges
31.2k3 gold badges62 silver badges183 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Mathematica Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f202884%2fdefining-a-function-programmatically%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Sorry, it is not at all clear to me what you try to achieve. Would you please give a concrete example?
$endgroup$
– Henrik Schumacher
9 hours ago
$begingroup$
@HenrikSchumacher I want to make the third code block based on the info given in the second code block. The code following “One possible solution...” does what I want, but it’s slow.
$endgroup$
– Chris K
9 hours ago
1
$begingroup$
Uuuh... Do you really want to have such a side effect in a pure function? Yes, Mathematica allows you to do that by I would not consider it programming practice.
$endgroup$
– Henrik Schumacher
9 hours ago
2
$begingroup$
It might be worth mentioning that you need this for a specific purpose (working with the
StateData
internals) such that it must be a pure function like this.$endgroup$
– b3m2a1
8 hours ago
1
$begingroup$
As @b3m2a1 alludes to, I do have a specific reason to achieve what I asked for. Maybe there's an easier way, but I thought it would be better to ask this question on its own rather than mixed in with that complicated project. Anyhow, I'll link to the Q&A that motivates this question as soon as I write it up.
$endgroup$
– Chris K
8 hours ago