Optional and orElse: design feedback/critique?

Johannes Loher johannes.loher at fg4f.de
Sat Jul 27 17:59:19 UTC 2019


Am 27.07.19 um 19:15 schrieb aliak:
> 
> How would you find using .each over ifPresent?
See my other answer. Though I don't care _that_ much. "each" might be a
bit awkward at times, but maybe it is good enough.
> As for ifPresentOrElse, would this suffice?:
> 
> no!int.orElse!(() => log("nothing there"));

I don't see how that has anything to do with ifPresentOrElse. Could you
please explain? In my other answer I also wrote a bit about why
ifPresentOrElse would be nice (and why match does not completely replace
it).

> Would you prefer an explicit orElseThrow or a throw_ expression as
> proposed in a previous post?

I don't actually care that much, but I think I slightly prefer
orElseThrow (probably because I'm used to it from Java). This is what I
have been doing in the past:

```
no!int.orElse!(function int() { throw new Exception(""); });
```

It is slightly annoying that you have to write the return type
explictly, but it's not that bad. I think I also wrote my own orElseThrow:

```
import optional;

auto orElseThrow(alias fun, T)(auto ref Optional!T opt)
{
    return opt.orElse!(delegate T() { throw fun(); });
}

void main()
{
    no!int.orElseThrow!(() => new Exception(""));
}
```
(you could make some improvements by checking (with static ifs) if a
delegate is actually needed, or a function suffices)

> Alright, more for separation of orElse's functions :) I must say that I
> quite like the coalesce functionality. But I think maybe you and Paul
> might be right to separate that and make it a different function. Or
> just not do the coalescing and the user can be a bit more explicit as I
> think Paul suggested.

Most of the time, I don't actually have a need for the overloads that
take a range, optional, nullable, so I'd be kind of OK with simply
removing it. I'd also totally be OK with it being a separate function.

What Paul suggested is not a good solution imo because it is besides the
point. Wrapping with optional after calling orElse is something totally
different than providing another optional as fallback, because in the
first case, you need to know that the fallback value is actually present
beforehand (in which case you should simply use the regular orElse
anyways). The value that the additional orElse overload currently
provides is that you can provide another fallback value of which you do
not know if it present as well and you can also chain this in a neat way:

/* ... */
enum fallback = 0;
return no!int
    .orElse(dbRequestThatMightOrMightNotReturnSomething())
    .orElse(httpRequestThatMightOrMightNotReturnSomething())
    .orElse(fallback);
/* ... */

As mentioned above, I do not use this that often, but I think it is
still a valid usecase and Pauls suggestion is not a substitute for it.



More information about the Digitalmars-d mailing list