3

This:

woof() {
        /usr/bin/woof -p $(expr $RANDOM % 32768 + 1024) $@
}

Always returns same number for parametr -p on zsh. In bash $(...) is evaluated on every call. Replacing $( ... ) with $[ ... ] 'fixes' this 'problem' in zsh for me but what is the issue or difference that causes unexpected behavior (unexpected for me at least)?

Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202
korda
  • 178
  • 5
  • 1
    that's why I quoted 'fixes' and 'problem'. I just want to know what's happening. I googled for quite a while and didn't found explanation so I'm asking a question. hopefully it will also help someone else who switched from bash to zsh – korda May 18 '17 at 09:37
  • 1
    I'd suggest migration to U&L personally... – djsmiley2kStaysInside May 18 '17 at 09:39
  • 3
    @djsmiley2k Asking about \*nix shells, including bash and zsh, is not off topic here. That a question would be "more on topic" somewhere else is not a reason to migrate unless it is actually *off* topic where it is, which this isn't. – user May 18 '17 at 14:03

1 Answers1

5

$( ) actually behaves the same way, it's the RNG which does not.

It seems that the zsh RNG is only advanced after referencing the value, but not reseeded when forking. This means subshells will just keep inheriting the old seed from the parent, as any changes happening in a subshell do not affect the parent process. Using $[…] does not have this problem as it doesn't create a subshell.

According to the zshall(1) manual page:

   RANDOM <S>
          A pseudo-random integer from 0 to 32767, newly generated each time
          this  parameter is referenced.  The random number generator can be
          seeded by assigning a numeric value to RANDOM.

          The values of RANDOM form an intentionally-repeatable  pseudo-ran‐
          dom sequence; subshells that reference RANDOM will result in iden‐
          tical pseudo-random values unless the value of  RANDOM  is  refer‐
          enced  or  seeded  in the parent shell in between subshell invoca‐
          tions.

Test:

% echo outer=$RANDOM; (echo inner=$RANDOM); (echo inner=$RANDOM);
outer=10246
inner=5606
inner=5606
u1686_grawity
  • 426,297
  • 64
  • 894
  • 966
  • And indeed referencing $RANDOM each time before using it in `$( )` has similar effect - in this case - to using `$[ ]` – korda May 19 '17 at 06:16