Re: Re: [RFC] Under Discussion: Add Random class and RandomNumberGenerator interface
| From: | Guilliam Xavier | Date: | Mon, 14 Jun 2021 09:31:18 +0000 |
| Subject: | Re: Re: [RFC] Under Discussion: Add Random class and RandomNumberGenerator interface | ||
| References: | 1 2 3 4 5 6 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-114854@lists.php.net to get a copy of this message | ||
> Indeed, the current implementation appears to have several problems. So,
> how about the following implementation?
>
> ```php
> interface RandomNumberGenerator
> {
> public function generate(): int;
> }
>
> final class Random
> {
> private RandomNumberGenerator $rng;
> public function __construct(?RandomNumberGenerator $rng = null)
> {
> $this->rng = $rng ?? new XorShift128Plus(random_int(PHP_INT_MIN,
> PHP_INT_MAX));
> }
> public function nextInt(): int {}
> public function getInt(int $min, int $max): int {}
> public function getBytes(int $length): string {}
> public function shuffleArray(array $array): array {}
> public function shuffleString(string $string): string {}
> public function __serialize(): array {}
> public function __unserialize(array $data): void {}
> }
>
> class XorShift128PlusNumberGenerator implements RandomNumberGenerator
> {
> public function generate(): int {}
> public function __serialize(): array {}
> public function __unserialize(array $data): void {}
> }
>
> class MT19937NumberGenerator implements RandomNumberGenerator
> {
> public function generate(): int {}
> public function __serialize(): array {}
> public function __unserialize(array $data): void {}
> }
>
> class SecureNumberGenerator implements RandomNumberGenerator
> {
> public function generate(): int {}
> }
> ```
>
> This is an approach similar to Nikita's
createDefault. If
> the
> constructor has a null argument, it uses the default, XorShift128+,
> internally.
>
> Also, whether the Random class is serializable or clonable depends on the
> instance of RandomNumberGenerator being used. This means that when the
> Random class clone is called, the $rng member will be
> implicitly cloned.
>
> How about this?
>
Hello, thanks for thinking again.
A few editorial notes:
- I guess that would be "new XorShift128PlusNumberGenerator" (like the
class name)?
- The non-Secure implementations' stubs are probably missing `public
function __construct(?int $seed = null) {}`?
- The Random class' and non-Secure implementations' stubs are probably
missing public function __clone(): void {} (like __serialize())?
That would let us use the API like this:
1. Construction: one of:
- default RNG and seed: $random = new Random();
- chosen RNG, default seed: e.g. `$random = new Random(new
MT19937NumberGenerator());`
- chosen RNG and seed: e.g. `$random = new Random(new
MT19937NumberGenerator(1234));`
(no "default RNG, chosen seed", but the default RNG can be documented,
and one could argue that a chosen seed only makes sense with a chosen RNG
anyway)
2. Usage: $int = $random->nextInt();, `$percent = $random->getInt(0,
100);, $dword = $random->getBytes(4);, $shuffledList =
$random->shuffleArray($list);` etc.
I think this is well-consistent with the "pure design" described by Nikita,
and I personally find it both flexible/extensible and easy-to-use =)
(Just beware that the namespace question will probably pop up again.)
PS: I feel like my numerous questions/suggestions (in this thread and the
previous ones) may also have caused some deviations, so I hope that I won't
need more and that other participants will reach a consensus...
Best regards,
--
Guilliam Xavier