# Is it possible to use RandomChoice to choose without other choices being evaluated?

I'm trying to do this:

i1 = 1;
i2 = 1;

RandomChoice[{
(i1 = i1 + 1),
(i1 = i1 - 1),
(i2 = i1 + 1),
(i2 = i2 - 1)}]


In order to chose randomly which variable is going to be incremented or decremented - but it's not working. I've also tried with -- and ++ but I had the same problem. I am clueless about what may be the problem.

May be the most compact approach:

Hold[i1++, i1--, i2++, i2--][[RandomInteger[{1, 4}]]]


Putting Increment or Decrement in third argument of Extract:

Extract[expr, list, h]

extracts parts of expr, wrapping each of them with head h before evaluation.

{i1, i2} = {1,1};
vars = Hold[i1, i2];

Extract[
vars
, RandomInteger[{1, Length@vars}]
, RandomChoice[{Increment, Decrement}]];


I'd do :

choices = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
{i1, i1} = {i1, i2} + RandomChoice[choices]


The problem is that the expressions inside RandomChoice[list] are evaluated before one of the elements in the list is picked. You can use the functions Hold and ReleaseHold to force the evaluation of the elements in the list to occur after the random choice like this:

ReleaseHold@RandomChoice[{Hold[i1++], Hold[i1--], Hold[i2++], Hold[i2--]}];


There are already many great answers here. Most of then work by holding various things unevaluated. I'd like to propose an alternative of sorts.

If we use indexed Symbols we can avoid unwanted premature evaluation without Hold or similar. Working with lists of "keys" is far easier than working with lists of assigned Symbols.

i[1] = 1;
i[2] = 1;

i[#@{1, 2}] += #@{-1, 1} & @ RandomChoice


That's two calls to RandomChoice, compressed with Function, one for the list of keys and one for the list of addends. Generalized:

roff[s_, keys_, os_, f_: RandomChoice] := s[f@keys] += f@os


Now:

i[_] = 1;

Do[
roff[i, {"a", "b", "c"}, {-7, -3, 2, 4, 6}],
{50}
]

i /@ {"a", "b", "c"}

{-7, 9, -3}


Note that you could use any other sampling function besides RandomChoice.

Or taking it in a different direction:

sampleApply[s_, keys_, fns_, R_: RandomChoice] := R[fns] @ s[R@keys]

j[_] = 0;

Do[
sampleApply[j, Range@5, {Increment, Decrement}],
{100}
]

Array[j, 5]

{3, -4, 2, 1, -6}


I hope these examples illustrate the flexibility and convenience of this approach.

• Avoiding Hold induced headache is always good +1 – ssch Sep 12 '13 at 18:53

Switch[RandomInteger[3], 0,++i1, 1,--i1, 2,++i2, _,--i2]

This is a more general approach, already made to a function: holdRandomChoice chooses randomly one of the listed commands without any of the others being evaluated:

SetAttributes[holdRandomChoice, HoldAll];
holdRandomChoice[list__] := Module[{x = Unevaluated@list},
Part[x, RandomInteger@{1, Length@x}]];

Clear[i];
holdRandomChoice[Print[i = 1], Print[i = 2], Print[i = 3]]
i

During evaluation of In[1]:= 2

Out[4]= 2


Note that none of the other commands got printed.

• FYI: you don't need Unevaluated or Module here; it would be a bit cleaner to use: Part[#, RandomInteger@{1, Length@#}] & @ Hold[list] – Mr.Wizard Sep 12 '13 at 19:44
• Actually, I would just write: holdRandomChoice[list__] := ReleaseHold @ RandomChoice @ Thread @ Hold @ {list} – Mr.Wizard Sep 12 '13 at 19:46

ReleaseHold@RandomChoice[{

ReleaseHold@RandomChoice[{