How to construct a list of Set's
I have a large set of parameters P which take several distinct sets of values V_i and want to use ActionMenu[]
to make assigning P=V_i easy, like so:
ActionMenu["Label", {"name_1" :> (P = V_1;),..}]
Now the problem is that the set of V_i's is large and not static, so instead of coding a long list {"opt_1" :> (P = V_1;),..}
over and over by hand, I'd like to generate it.
I am completely stumped at how to do it. The general approach is something like
Thread@RuleDelayed[listOfNames,listOfActions]
where listOfActions
should be something like
Thread@Set[repeatedListOfP,listOfV_i]
But this does not work. And since Set[]
is a very special function, none of my other usu开发者_如何学运维al approaches work (building a Table[]
, replacing headers, etc). How do you go about constructing a list of Set[]
operations?
There may be more to your question that I haven't grokked yet but maybe this will get you on the right track.
This
MapThread[Hold[#1 = #2]&, {{a, b, c}, {1, 2, 3}}]
returns a list of unevaluated "Set"s like so:
{Hold[a = 1], Hold[b = 2], Hold[c = 3]}
If you call ReleaseHold on the above then the assignments will actually happen.
More on Hold and relatives here:
Mathematica: Unevaluated vs Defer vs Hold vs HoldForm vs HoldAllComplete vs etc etc
Here's an alternative solution that I've used when I've wanted to have RuleDelayed
applications that have side-effects. You use a different head to substitute in for Set
until you have your expression on the right-hand side of a RuleDelayed
form (where it'll be held by RuleDelayed
's HoldRest
attribute) and then subsitute Set
back in. When I do this, I like to use Module
to create a unique symbol for me. This way you don't have to use Defer
, which is an even more unpleasantly slippery construct than Unevaluated
.
Here's an example:
Module[{set},
Attributes[set] = Attributes[Set];
With[{rhs = MapThread[set, Unevaluated[{{x, y, z}, {1, 2, 3}}]]},
"name1" :> rhs /. {set -> Set, List -> CompoundExpression}]]
The reason the set
symbol is given the same attributes as Set
, and the reason the Unevaluated
is there, is to make sure this works even if someone has already assigned a value to x
, y
or z
.
Another possibility is to wrap all your Set
expressions up as closures and then use Scan
to call them when the RuleDelayed
is evaluated, like so:
With[{thunks = MapThread[Function[{a, b}, (a = b) &, HoldAll],
Unevaluated[{{x, y, z}, {1, 2, 3}}]]},
"name1" :> Scan[#[] &, thunks]]
精彩评论