tags:

views:

67

answers:

2

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 usual approaches work (building a Table[], replacing headers, etc). How do you go about constructing a list of Set[] operations?

+2  A: 

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:
http://stackoverflow.com/questions/1616592/unevaluated-vs-defer-vs-hold-vs-etc

dreeves
You've hit the nail on the head with "...then the assignments will actually happen". I need Mathematica to give me a literal list of `{(a=1);,(b=2);,...}` without evaluating but also without any Hold[] structures left in there.
Timo
YES! Defer[] does the trick.
Timo
+1  A: 

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]]
Pillsy