Range Redesign: Copy Semantics

H. S. Teoh hsteoh at qfbox.info
Mon Jan 22 17:07:05 UTC 2024


On Mon, Jan 22, 2024 at 03:41:35PM +0000, Atila Neves via Digitalmars-d wrote:
> On Sunday, 21 January 2024 at 05:00:31 UTC, Jonathan M Davis wrote:
> > I've been thinking about this for a while now, but with the next
> > version of Phobos which is in the early planning stages, we really
> > should do some redesigning of ranges. Most of their API is just fine
> > how it is, but there are some aspects of it which really should be
> > changed if we want them to be better (the most obvious one being the
> > removal of auto-decoding). But what I'd like to discuss specifically
> > in this thread is fixing - and defining - the semantics of copying
> > and assigning to ranges. Specifically, the semantics of stuff like
> > 
> > [...]
> 
> I don't think I've ever encountered a situation where reference ranges
> would have been desirable - I've never used one.

It's useful in recursive-descent parsers where you expect the range to
have advanced past whatever a recursive call has consumed.


> I think that `.save` was a historical mistake, and that ranges that
> can be copied are forward ranges. Something like a range reading from
> stdin or a socket would/should disable the copy/postblit constructors.

Meaning they can only be passed by reference?


> Has anyone here used the class-based ranges?

Yes.  They are useful when you have a range whose type varies at
runtime. For example:

	auto myFunc(R)(R range, int type) {
		switch (type) {
			case 1:
				return range.map!(a => a*2);
			case 2:
				auto auxRange = helperFunc(range);
				return range.filter!(a => a % 2)
					.chain(auxRange);
			case 3:
				return range.chain(recurrence!(...));
		}
		assert(0);
	}

This code will not compile because there is no common return type. To
fix it, wrap each return in out of the class-based range objects:

	auto myFunc(R)(R range, int type) {
		switch (type) {
			case 1:
				return range.map!(a => a*2)
					.inputRangeObject;
			case 2:
				auto auxRange = helperFunc(range);
				return range.filter!(a => a % 2)
					.chain(auxRange)
					.inputRangeObject;
			case 3:
				return range.chain(recurrence!(...))
					.inputRangeObject;
		}
		assert(0);
	}


T

-- 
They say that "guns don't kill people, people kill people." Well I think the gun helps. If you just stood there and yelled BANG, I don't think you'd kill too many people. -- Eddie Izzard, Dressed to Kill


More information about the Digitalmars-d mailing list