takeBack() implementation in std.range for OutputRanges

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon Sep 2 02:25:24 UTC 2024


On Sunday, September 1, 2024 3:16:31 PM MDT Salih Dincer via dip.ideas wrote:
> On Saturday, 31 August 2024 at 22:29:57 UTC, monkyyy wrote:
> > On Saturday, 31 August 2024 at 17:55:17 UTC, Salih Dincer wrote:
> >> Why have a function called dropBack() but not takeBack()?
> >
> > probably retro.take is considered good enough? When
> > retro.drop.retro isnt
>
> The problem is that, whether retro() or dropBack() works with
> BidirectionalRange. So we need to find different solutions. If
> everything was an array, things would be easier, but I don't know
> how to get the last 4 elements of a range of known length, other
> than filtering! Does anyone have another practical solution?

The fact that a range's length is known is not sufficient to be able to get
at the elements at its end. In most cases, a range with length is a
bidirectional range or random-access range, but it is possible to have a
forward range with length (e.g. because takeExactly was used to create it),
and the forward range API provides no direct way to get at the elements at
its end.

Fundamentally, you cannot get at the end of a range that isn't a
bidirectional or random access range without popping off all of the
preceding elements. The API gives us no way to do it, and plenty of ranges
cannot implement that kind of functionality (otherwise, they'd be
bidirectional or random-access ranges).

If you have a random-access range, they're generally sliceable (and probably
should require that they be sliceable, but IIRC, they currently don't for
some reason), so you can just slice the end (and if for some weird reason a
random-access range doesn't have slicing, it's trivial to create a wrapper
that does the same thing by using the indices).

And if you have a bidirectional range, then you can use retro and take
(though you then have a range in the reverse order and can't use retro on
the result, since bidirectional ranges provide no way to access the middle
of a range).

If you want to be able to just take the last n elements of a range and have
them be in the same order, you need a random-access range. The range API
provides no other way to do it, and if a range is not a random-access range,
then it's usually because it can't efficiently be one for one reason or
another (though in some cases, it's because the programmer didn't bother to
add the full range capabilities that they could, because they didn't need
them for what they were doing).

If you want to do something like fwdRange.takeBack(5), then that's simply
never going to work unless the original range is a random-access range,
because that range type doesn't provide a way that that could be implemented
efficently.

- Jonathan M Davis





More information about the dip.ideas mailing list