foreach() behavior on ranges

Steven Schveighoffer schveiguy at gmail.com
Wed Aug 25 11:49:18 UTC 2021


On 8/25/21 7:26 AM, Alexandru Ermicioi wrote:
> On Wednesday, 25 August 2021 at 11:04:35 UTC, Steven Schveighoffer wrote:
>> It never has called `save`. It makes a copy, which is almost always 
>> the equivalent `save` implementation.
>>
> 
> Really?
> 
> Then what is the use for .save method then?
> The only reason I can find is that you can't declare constructors in 
> interfaces hence the use of the .save method instead of copy constructor 
> for defining forward ranges.

The `save` function was used to provide a way for code like 
`isForwardRange` to have a definitive symbol to search for. It's also 
opt-in, whereas if we used copying, it would be opt-out.

Why a function, and not just some enum? Because it should be something 
that has to be used, not just a "documenting" attribute if I recall 
correctly.

Keep in mind, UDAs were not a thing yet, and compile-time introspection 
was not as robust as it is now. I'm not even sure you could disable copying.

> 
> We have now two ways of doing the same thing, which can cause confusion. 
> Best would be then for ranges to hide copy constructor under private 
> modifier (or disable altoghether), and force other range wrappers call 
> .save always, including foreach since by not doing so we introduce 
> difference in behavior between ref and value forward ranges (for foreach 
> use).

There would be a huge hole in this plan -- arrays. Arrays are the most 
common range anywhere, and if a forward range must not be copyable any 
way but using `save`, it would mean arrays are not forward ranges.

Not to mention that foreach on an array is a language construct, and 
does not involve the range interface.

-Steve


More information about the Digitalmars-d-learn mailing list