Problem with function inside brackets. Bug?

No, not a bug.

Let's think about how AppendTo may be implemented (even though the actual implementation isn't inspectable).

SetAttributes[appendTo, HoldFirst]
appendTo[a_, val_] := (a = Append[a, val])

What happens if we evaluate the following?

appendTo[ a[[ RandomInteger[{1,3}] ]],  x ]

It simply does this:

a[[ RandomInteger[{1,3}] ]] = Append[a[[ RandomInteger[{1,3}] ]], x]

That's because RandomInteger[...] didn't get evaluated before substitution due to the HoldFirst. Now we have two of them. And they may evaluate to different values. So we may get things like

a[[1]] = Append[ a[[3]], x ]

if the first random number we get is 1 and the second is 3.

I hope this makes it clear. I have a vague feeling that the same has been asked before in a different form.


Here's the issue. In the second (non-working) code,

RandomInteger[{1, Length[a]}]

is evaluated twice, as we can see by Traceing the evaluation:

SeedRandom[2]
a = {{1}, {2}, {3}};
Trace[AppendTo[a[[RandomInteger[{1, Length[a]}]]], RandomInteger[9]], TraceInternal -> True]
  1. {RandomInteger[9], 8}
  2. AppendTo[a[[RandomInteger[{1, Length[a]}]]], 8]
  3. {{a, {{1}, {2}, {3}}}, {{{{a, {{1}, {2}, {3}}}, Length[{{1}, {2}, {3}}], 3}, {1, 3}}, RandomInteger[{1, 3}], 3}, {{1}, {2}, {3}}[[3]], {3}}
  4. a[[RandomInteger[{1, Length[a]}]]] = Append[{3}, 8]
  5. {Append[{3}, 8], {3, 8}}
  6. a[[RandomInteger[{1, Length[a]}]]] = {3, 8}
  7. {{{{a, {{1}, {2}, {3}}}, Length[{{1}, {2}, {3}}], 3}, {1, 3}}, RandomInteger[{1, 3}], 2}

We can see in Line 1 that RandomInteger[9] evaluates to 8, so we will be appending 8 to one of the lists. In Line 3, RandomInteger[{1, 3}] evaluates to 3, so we're going to append to a[[3]]. This happens on Line 5, where 8 is appended to {3} to make {3, 8}.

Now, the kicker: In Line 7, RandomInteger[{1, Length[a]}] is evaluated again, so it evaluates to a different number. In this case, it evaluates to 2, so instead of replacing a[[3]], we are replacing a[[2]] with {3, 8}. Hence the output after this evaluation is

a
(* {{1}, {3, 8}, {3}} *)

Now, the fix here is to do things the way you're doing it in the first code. I would probably wrap the entire thing in a Module with j as a local variable, but it's the same process.