It’s true, but I would advise exploring library-only alternatives first.
For example, I just coded something that lets you do the following:
val answer =
attempt:
val a = aOpt.?
val b = bOpt.?
bar(b, a).? // bar(a, b) returns Boolean
foo(a, b)
.default:
d
The ability of Scala 3 to create custom very low overhead (low runtime overhead and low syntactic overhead) syntax like this is pretty good. Yes, it doesn’t have the actual comprehension, so you have to type val
a couple of times. But if you interpret .?
as “get a value, or run a test, and bail out otherwise”, then it’s really compact and clear. And it’s a 100% library solution.
Don’t want to save the unpacked options? Fine. Just unpack them again:
val answer =
attempt:
bar(bOpt.?, aOpt.?).?; foo(aOpt.?, bOpt.?)
.default:
d
One-liner? Okay, you can:
val answer = attempt{ bar(bOpt.?, aOpt.?).?; foo(aOpt.?, bOpt.?) }.default(d)
Yes, it does take a little more getting used to than a new language construct, but the advantage is that you don’t have to convince anyone of anything to start using this. It just takes a bit of code. (And Scala 3.3 with boundary/break
.)
If you want to sequence with &&
instead of ;
, that’s easy enough too. Want to chain multiple .attempt
s? Also easy.