Optional and orElse: design feedback/critique?

aliak something at something.com
Sun Jul 28 03:13:15 UTC 2019


On Saturday, 27 July 2019 at 17:59:19 UTC, Johannes Loher wrote:
> 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).

Sorry, I misunderstood. So basically:

if (a.empty)
   fun();
else
   value += 1;

So Scala provides this with match out of the box by promoting 
(demoting?) the types to Any, and indeed the current match can be 
made to do the "same" (if the return types are incompatible, then 
there's no return, i.e. void). Should work no? If you mess up 
types the compiler will shout so it sounds, sound.

Btw, this reminds me of an optional vs matching cheat sheet that 
I was pointed to some time ago and thought it was great! -> 
https://www.originate.com/thinking/stories/idiomatic-scala-your-options-do-not-match/

>
>> 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)

Yes. I've done this as well. So I think I'll add this in.

>
>> 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.

Yes, I agree that's a nice use-case (which I use). I think I'll 
probably go with frontOrElse and orElse to separate the 
functionality. Something is screaming flatMap to me right now but 
I just can't put my finger on it ;)




More information about the Digitalmars-d mailing list