# How can I use replacement rules with randomized values? [closed]

Suppose I have a list that I want to use replacement rules to replace each occurrence of a a given symbol with a randomly selected value, with this choice being randomized for each occurrence.

For a simple example, suppose list={x,x,x,x} and I want to replace each occurrence of x with a (potentially different) random integer between 1 and 5. Defining

    rule=x->RandomInteger[5]


and evaluating list/.rule instead replaces all the instances of x with the same randomly chosen value. For example, returning {5,5,5,5} instead of {2,3,3,5}.

How can I obtain the properly randomized replacements?

The issue with defining rule = x -> RandomInteger[5] and evaluating it is that Mathematica evaluates this RandomInteger at the time of definition, simply storing rule = x -> 5 or similar. This in turn causes list /. rule to replace all of the x with the same value.

Instead, we need to delay this random choice so that it occurs after it has replaced each x.

A solution is to use :> (RuleDelayed) instead of -> (Rule), which holds the RHS unevaluated until the rule is used. This syntactic distinction is similar to that of = (Set) vs := (SetDelayed):

   delayRule = x :> RandomInteger[5];
list /. delayRule
(* {2, 3, 1, 4} *)


An alternative solution is to use Hold and ReleaseHold to obtain the desired behavior:

randomRule = x -> Hold[RandomInteger[5]];

list /. randomRule
(* {Hold[RandomInteger[5]], ...., Hold[RandomInteger[5]]}*))

% // ReleaseHold
(* {4, 2, 3, 2} *)


Observe how using Hold in our rule replaces each x with a separate copy of Hold[RandomInteger[5]]. We then ReleaseHold to have the kernel evaluate each copy, giving our separately evaluated random choices.

You want RuleDelayed instead of Rule so the right hand side of the rule is recalculated every time the replacement rule is applied:

rule = x:> RandomInteger[5];
{x, 10, 10, x, 10} /. rule

(* Out: {3, 10, 10, 5, 10} *)
`