How do you safely deal with range.front?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Fri Dec 29 20:33:22 UTC 2017


On Friday, December 29, 2017 19:38:44 aliak via Digitalmars-d-learn wrote:
> Hi,
>
> So when I'm dealing with ranges, there're a number of times where
> I get the front of the returned result of a set of operations,
> but of course there is no front so you get an runtime access
> error.

You don't necessarily get a runtime access error. It is undefined behavior
to call front on a range that's empty, and what happens depends entirely on
how the range is implemented. In plenty of cases, you'll get really weird
stuff happening and no obvious error. It is a bug for any code to call front
when empty is true.

> In some other languages the concept of "front" or "first" returns
> a safe referece, or optional value that calling methods on will
> not crash the program.
>
> I'm thinking of maybe making something like
>
> safeFront(R)(R r) {
>    return r.empty ? SafeRef!(ElementType!R) : SafeRef(r.front);
> }
>
> Where SafeRef, I think, can provide an overload for opDispatch
> and just forward the calls to the stored reference of r.front. If
> the stored reference is null then it can return a SafeRef to the
> return value of whatever was being dispatched to.
>
> Is there another way to go about this? Maybe through naturally
> using r.front instead of making a r.safeFront alternative?

Well, I don't know what you're really doing in code here, but in general,
you'd write your code in a way that it checks empty and simply doesn't try
to do anything with front if the range is empty. If you're trying to require
that there's a front regardless of whether there is one, that sounds to me
like you're just asking for trouble, and if it were me, I'd refactor my code
so that that sort of thing wasn't happening. But if you have a use case
where that really does make sense, then there are a few options.

You could wrap the range in a range that returns a Nullable!(ElementType!R)
and return null when there is no front, which would then require the calling
code to check whether the Nullable was null rather than checking the range
for empty.

You could wrap the range in a range that specifically returns some default
element when the wrapped range is empty, meaning that the range would then
be infinite.

You could just use a wrapper function to call front and have it return a
Nullable or a default value if the range is empty, but that wouldn't work
when passing the range to other functions.

You could also do something like an infinite range that simply returns the
same value forever no matter how often front gets popped, and then you could
use chain to combine your range and that range into a single range that
would iterate through your range and then give the same element forever.

Regardless, you'll have to be careful of any solution that involves creating
an infinite range, since while some algorithms will be fine with it, others
will either not compile or result in an infinite loop (e.g. don't use
foreach on it).

Regardless, if you want to return an element when there isn't one, you're
going to have to come up with a value for that. It's not something that's
really going to work well generically. The closest would be the init value
of the element type, but how much that makes sense depends on the element
type and what you're doing.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list