User defined type and foreach

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Jan 25 10:30:35 UTC 2024


On Thursday, January 25, 2024 1:57:56 AM MST Jim Balter via Digitalmars-d-
learn wrote:
> The specification of ranges, which is independent of
> the D language, says that the way to copy a range is to use
> save().

I'm sorry, but you're misunderstanding the range specification if you think
that save is the only way to copy a range or that the range specification
makes any such guarantee. And if there is any official documentation that
makes any such claim, then it needs to be fixed, because ranges have never
worked that way, and they cannot work that way unless ranges in general are
non-copyable, which is not the case at all.

What save does is give you a guaranteed way to get a copy which can be
independently iterated. However, it's perfectly valid to simply copy a range
and then use the copy. They're not non-copyable types, and range-based code
in general copies ranges all over the place - both with basic input ranges
and with forward ranges. They're copied when they're passed to functions.
They're copied when they're wrapped by other ranges. They're copied when
they're passed to foreach. This is all falls within the expected use of
ranges. What you don't get from those copies is the guarantee that the copy
is independent, which is why save is necessary in cases where you need to be
sure that you're getting an independent copy of a range.

I gave that long explanation to try to get across what was happening with
the copy semantics of ranges and what the consequences of that are. If that
wasn't helpful to you, then I'm sorry. Either way, if you think that it goes
against the range API to copy a range any way other than by calling save,
then you are misunderstanding how ranges work, and looking at how Phobos
uses ranges should make that clear, because it copies them all over the
place, including with code that works on basic input ranges.

The range API guarantees that copying a range will result in the copy having
the same elements in the same order as the original would have had had it
not been copied, because without that guarantee, range-based code in general
simply wouldn't work. Range-based code in general relies on that ability to
copy a range when passing it around. Now, what happens to the original after
the copy has been made is not specified by the range API, and that's why
save is necessary. But you can still copy a range and use that copy in
generic code so long as you don't touch the original again.

So, I've tried to explain to you why the current behavior is expected and
does not violate the range specification. If that's not enough for you, then
I'm sorry. Maybe someone else can help you out, but if what you've said
about save were correct, then Phobos as a whole would be violating the range
specification - as would the language itself with foreach. But they've been
working this way for well over a decade.

We would like to improve the situation with the next major version of Phobos
so that the copy semantics of ranges are cleaner, and the range API will
likely see a redesign to fix that issue, among others, but the current range
API is as I've explained it to you, warts and all.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list