Reputation: 513
getRandom () {
echo $RANDOM
}
getRandomFromGetRandom () {
echo $(getRandom)
}
Calling getRandom
does the expected every time, it returns some random number on each call.
What I'd expect is the same from getRandomFromGetRandom
, that a random number being called every time I call getRandomFromGetRandom
, but that's not the case. Every time that function is called it returns a constant which changes only when I open another instance of the terminal.
Upvotes: 2
Views: 199
Reputation: 50775
man zshparam
says:
The values of RANDOM form an intentionally-repeatable pseudo-random sequence; subshells that reference RANDOM will result in identical pseudo-random values unless the value of RANDOM is referenced or seeded in the parent shell in between subshell invocations.
Since command substitution is performed in a subshell, this explains the repetitive values getRandomFromGetRandom
prints. To fix it, reference RANDOM
before echoing $(getRandom)
, like
getRandomFromGetRandom () {
: $RANDOM
echo $(getRandom)
}
Or seed it (zsh-only; won't work on yash)
getRandomFromGetRandom () {
RANDOM= echo $(getRandom)
}
Upvotes: 4
Reputation: 14452
(Almost) All Random implementations are based on saved state. Calculating the value of the next random number depends only on the state, and will modify the state so that the next call will yield different number. When a process is forked, the state of the parent is copied into the state of the children.
In the posted code, the getRandom is calculated in a sub-shell (because of $(getRandom)
). As a result, the code repeated uses the inherit state from the parent, which is never updated. The next call therefore will use the same (parent) state, and will result in the same number.
The first two iterations will look like:
Iteration 1:
Iteration 2:
The following shows how to get similar logic to work
getRandom () {
my_random=$RANDOM
}
getRandomFromGetRandom () {
getRandom
echo "$my_random"
}
getRandomFromGetRandom
getRandomFromGetRandom
Upvotes: 2