Move semantics for D
monarch_dodra
monarch_dodra at gmail.com
Fri Jul 13 04:45:19 PDT 2012
On Friday, 13 July 2012 at 10:33:13 UTC, Jonathan M Davis wrote:
> On Friday, July 13, 2012 12:24:45 monarch_dodra wrote:
>> On Friday, 13 July 2012 at 09:47:26 UTC, Jonathan M Davis
>> wrote:
>> > On Friday, July 13, 2012 11:23:41 monarch_dodra wrote:
>> >> I think that in the case of your example, if "range"
>> >> fulfills
>> >> the
>> >> requirements for (at least) an input range, then "save"
>> >> *should*
>> >> be called instead of "opSlice". I'm *think* this is what the
>> >> compiler does, but I'm not 100% sure.
>> >
>> > The compiler never calls save. It will call opSlice on
>> > non-ranges, but it'll
>> > never call save on anything. It doesn't even know that save
>> > exists. It's
>> > unnecessary for ranges which aren't reference types, and you
>> > already have to
>> > worry about calling save on ranges that could be reference
>> > types any time that
>> > you pass them to a function that you don't want to consume
>> > it,
>> > so it's not
>> > really a big deal to have to call save with foreach for such
>> > ranges. Most
>> > range-based functions don't even use foreach much anyway.
>> >
>> > - Jonathan M Davis
>>
>> What exactly are the semantics of save? The reference in
>> std.range isn't very clear. It would appear it is only useful
>> it
>> its *existence* that promotes a range from input to forward.
>> However, how is it different from a simple assignment?
>>
>> Also, if you are supposed to call save before a foreach
>> "consumes" your range, then why does foreach even bother
>> making a
>> copy of the range before iterating on it? Isn't this behavior
>> promoting dangerous usage for ranges where save is simply
>> "{return this;}", but bites you in the ass the day you use a
>> range with a specific save?
>>
>> I'm confused...
>
> save exists so that classes can be forward ranges. Arrays and
> most structs are
> copied when you assign them to another variable or pass them to
> a function,
> but classes aren't. So, save was introduced to make it so that
> there is a way
> to explicitly copy a range. It becomes useful even for structs
> and arrays in
> that it documents that you're copying it, but it's outright
> necessary for
> classes. Unfortunately, since arrays and structs are by far the
> most common
> range types, save doesn't get used anywhere near as much as it
> should be.
> Basically, you use save if you want to guarantee that the range
> is copied, and
> you don't use save if you don't care.
>
> You can also look at this:
>
> http://stackoverflow.com/questions/11190204/how-do-you-use-ranges-in-
> d/11194827#11194827
>
> - Jonathan M Davis
I guess that "save" makes sense thanks in that context. Thank you.
However, foreach is starting to look very dangerous to me: Isn't
the fact that it (potentially) calls opSlice, or makes a copy of
your input just a asking for potential problems? Or is this a
"struct vs class" issue, that I do not yet fully grasp?
Shouldn't we instead enforce an _explicit_ opSlice/save? Eg:
auto SomeContainer = ... ;
auto SomeRange = SomeContainer[ ... ];
foreach(v; SomeContainer[]) ... ; //Fine, iterate on a new range,
and consume that
foreach(v; SomeRange.save) ... ; //Fine, iterate on a copy of
the range, and comue that
foreach(v; SomeContainer) ... ; //Fine, I will NOT call opSlice,
and _consume_ your container
foreach(v; SomeRange) ... ; //Fine, I will NOT copy, and
_consume_ your range
...
I suppose the "recommendation" is to use the above form, and that
is what I will be doing as of now on.
But I still feel that the call to opSlice/copy is really a just
trap disguised as a safety net...
More information about the Digitalmars-d
mailing list