Reference semantic ranges and algorithms (and std.random)

Johannes Pfau nospam at example.com
Thu Sep 20 02:59:40 PDT 2012


Am Thu, 20 Sep 2012 08:51:28 +0200
schrieb "monarch_dodra" <monarchdodra at gmail.com>:

> > Moving to classes would definitely break code, but it should be 
> > possible to
> > make them reference types simply by making it so that their 
> > internal state is
> > in a separate object held by a pointer.  
> 
> I was thinking of doing that. The problem with this (as I've run 
> into and stated in another thread), is a problem of 
> initialization: The simpler PRNGs are init'ed seeded, and are 
> ready for use immediately. Changing to this approach would break 
> the initialization, as shown in this post:

How would the internal state be allocated? malloc + refcounting or GC?

I'm not really happy about that as I'd like to avoid allocation
(especially GC) whenever possible. Using a PRNG only locally in a
function seems like a valid use case to me and it currently doesn't
require allocation. As the similar problem with
std.digest/std.algorithm.copy has showed value type ranges seem not
very well supported in phobos.

I wonder why we don't pass all struct/value type ranges by ref? Is
there a reason this wouldn't work?

Or we could leave the PRNGs as is and provide reference wrappers. This
would allow to place the PRNG on the stack and still make it work with
all range functions. But it's also cumbersome and error prone.

Best solution is probably to have wrappers which allocate by default,
but also allow to pass a reference to a stack allocated value. Then
make the wrappers default, so the default's safe and easy to use.

Pseudo-code:

struct RNG_Impl
{
    uint front();
    void popFront();
    bool empty();
}

struct RNG
{
    RNG_Impl* impl;

    this(ref RNG_Impl impl)
        impl = cast(RNG_Impl*) impl;

    void initialize()
    {
        assert(!impl); //Either initialize or constructor
        impl = new RNG_Impl();
    }
}

RNG_Impl impl;
RNG(impl).take(5); //No allocation (but must not leak references...)

Regarding the initialization check: I'd avoid the check in release
mode. Not initializing a struct is a developer mistake and should be
found in debug mode. I think it's unlikely that error handling code can
handle such a situation anyway. But you could check how
std.typecons.RefCounted handles this, as it also need explicit
initialization. 


More information about the Digitalmars-d mailing list