On 26/08/13 17:26, monarch_dodra wrote:
One more thing. One of the ways I see it (specifically for LF): We can add
auto-seed later if we decide it was a bad idea to not have it. The opposite
isn't possible.
Yes. I feel similar about the question of whether or not pseudo-random RNGs
should have .save methods or not. I can see use-cases, but better to avoid at
first (while as you have suggested implementing .dup) and then, if it turns out
that was a bad idea, add them.
Another option I had thought of, was to make the value-types Payloads as public,
with *massive* "do not use signs". *We* then provide simple and generic (and
pure/nothrow) GC-based wrappers.
Related to this, I was thinking about how my RandomGenerator implements the
isUniformRandom property (it aliases to the corresponding property of the
underlying random engine/payload).
Now, if you suppose that the payloads _don't_ define isUniformRandom but define,
say, isRandomPayload or isRandomEngine, and then in the RandomGenerator wrapper
you have,
alias isUniformRandom = Payload.isRandomPayload;
... then the isUniformRNG check of other functions WON'T WORK with the raw
Payloads. So you have a static safety check in place that will plain stop users
doing stupid stuff.
That is beneficial, because it means that a user can for example make use of the
Payload definition to define a new RNG of existing type but with different
configuration (e.g. Lagged Fib with different parameter values).
From there, if, for whatever reason, a user needs malloc allocation, or heck,
static allocation, he still has an "underhand" access to the payload
implementation, but lifecycle management remains *his* responsibility.
I think: Simple and safe by default, with the possibility for extension.
Yes, if we handle isUniformRandom like this.
Again, for now, I think this is implementation detail. That said, I don't buy
much into the typo argument. In particular, this is something that gets copy
pasted only once, so we should be relatively safe.
One of the arguments in favor of "internal" mixins is that of extension: For
example, laggedFib has a very real reason to implement popFrontN, as it can
potentially pop thousands of elements at once in o(1). "Internal" mixin makes it
easy to extend a PRNG's capabilities past that of the "lowest common
denominator". With a "alias Random = RandomGenerator!RandomPayload", you are
really limited to whatever RandomGenerator wrapped.
Fair enough, but I think there are other ways of handling that, e.g. via
opDispatch. We ought to be able to make sure that _all_ public methods and
properties of the payload get forwarded.
And -- devil's advocate -- how many different extensions are there likely to be
in practice? Is it not the case that we can anticipate them and make sure they
are in the wrapper? How many operations can one reasonably expect from a RNG?
Honestly, it might just be the simplest thing to do. For one, it would elegantly
solve the "must be seeded" issue (allocation is initialization). It *guarantees*
Reference semantics. Finally, the (supposed) overhead should be inexistant
compared to the compelxity of a PRNG.
The option of allowing "public Payload" definitions could still leave an open
door for those that need PRNG's, but don't use the GC (think vidjagames).
I would quite like to have Andrei and Walter's input on the struct vs. class
aspect, and Phobos design style.
One thought about "public payload" and wrappers: it ought to be possible to
design things so that a RandomGenerator wrapper can be initialized by passing a
pointer-to-payload instead of a seed, which obviates the need for internal
allocation. And we can use that approach for rndGen() so that the default RNG
instance doesn't require GC.