Re: Re: [RFC] Under Discussion: Add Random class and RandomNumberGenerator interface

From: 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

« previous php.internals (#114854) next »