Struct that destroys its original handle on copy-by-value

Joseph Rushton Wakeling via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Aug 1 05:03:19 PDT 2015


On 31/07/15 19:21, Ali Çehreli via Digitalmars-d-learn wrote:
> On 07/26/2015 04:29 AM, Joseph Rushton Wakeling via Digitalmars-d-learn wrote:
>
>  > is this design idea even feasible in principle, or just a bad
>  > idea from the get-go?
>
> As I understand it, it is against one of fundamental D principles: structs are
> value types where any copy can be used in place of any other.
>
> I expect there are examples where even Phobos violates it but the struct
> documentation still says so: "A struct is defined to not have an identity; that
> is, the implementation is free to make bit copies of the struct as convenient."
>
>    http://dlang.org/struct.html

That really feels very bad for the problem domain I have in mind -- random 
number generation.  No implementation should be free to make copies of a random 
number generator "as convenient", that should be 100% in the hands of the 
programmer!


>  > And if feasible -- how would I go about it?
>
> Disallowing automatic copying and providing a function comes to mind.

Yes, I considered that, but I don't think it really delivers what's needed :-(

Let me give a concrete example of why I was thinking in this direction. 
Consider RandomSample in std.random.  This is a struct (a value type, 
instantiated on the stack).  However, it also wraps a random number generator. 
It needs to be consumed once and once only, because otherwise there will be 
unintended statistical correlations in the program.  Copy-by-value leads to a 
situation where you can accidentally consume the same sequence twice (or 
possibly, only _part_ of the sequence).

Now, indeed, one way is to just @disable this(this) which prevents 
copy-by-value.  But then you can't do something natural and desirable like:

     iota(100).randomSample(10, gen).take(5).writeln;

... because you would no longer be able to pass the RandomSample instance into 
`take`.

On the other hand, what you want to disallow is this:

    auto sample = iota(100).randomSample(10, gen);

    sample.take(5).writeln;
    sample.take(5).writeln;   // statistical correlations result,
                              // probably unwanted

The first situation is still possible, and the second disallowed (or at least, 
guarded against), _if_ a copy-by-value is finalized by tweaking the source to 
render it an empty range.

I would happily hear alternative solutions to the problem, but that's why I was 
interested in a struct with the properties I outlined in my original post.



More information about the Digitalmars-d-learn mailing list