Totally overlooked this thread, sorry. Thanks @steph for bringing this up
In a nutshell, here’s what actually happens:
-
The RNG (random number generator) used in Coda is, of course, a pseudo-random one. This means it doesn’t generate true randomness from e.g. atmospheric noise like Random.org does, but generates a sequence of pseudo-random numbers (i.e. statistically they would appear random and equally distributed) based on the initial value called seed, and some transformation algorithm (probably not LCG but study this one to get the idea)
-
Yeah, given that the algorithm stays the same, RNG will produce the same sequence of numbers for the same seed.
-
In Coda, it seems like the RNG never produces the sequence of numbers but only takes one. So as long as the seed is the same, the output is also the same.
-
As a seed, Coda uses the combination of:
- The Latest Doc modification timestamp, and
- Object ID / Table ID and Row ID
-
Finally, running actions (e.g. adding or modifying rows) does NOT guarantee that the doc edit timestamp will refresh right away, even if the action is enclosed within
RunActions()
to wait for recalcs. I don’t know the exact reason for this but most likely it’s either:- It’s refreshed by the server, once the op is actually applied (e.g. when the row is actually added to the table, as evident by the appearing row ID)
- It simply has second-level precision, i.e. Random() can only refresh once in a second.
So that’s why the behavior of Random()
is as it is. It gives different values in different canvas formulas and for different rows of a table (because the seed uses object ID and row ID), but it gives the same values within one formula (same object ID and same timestamp), and it gives repeated values when adding rows (rows are being added faster than they are saved to the doc and recorded as edits). Adding _Delay()
s kinda helps, but it’s not reliable because there’s no guarantee that 300 or whatever milliseconds would be enough to save the next edit — something may lag time to time and the trick won’t work.
The seemingly easy fix would be to only keep one Random() instance and never refresh the seed but simply query the next value instead. However remember that multiple people may be working on the same Coda doc at once (incl. offline), so Random() has to predictably work across connected users. That’s probably why it’s implemented the way it is, and is not so easy to fix.
The only way to get a sequence of random items that are reliably pseudo-random and don’t have these issues is to get these from a column with enough rows. The trick with the temporary table is one way to solve it.