CLOVIS
03/25/2024, 9:53 PMfun logIn(username: String, password: String) = either {
val (validUsername, validPassword) = zipOrAccumulate(
{ withError(LogInFailure::InvalidUsername) { usernameOf(username) } },
{ withError(LogInFailure::InvalidPassword) { passwordOf(password) } },
) { u, p -> u to p }
…further processing…
}
and this overall pattern is quite verbose 😕Kev
03/26/2024, 2:35 AMfun logIn(username: String, password: String) = either {
val (validUsername, validPassword) = zipOrAccumulate(
{ withError(LogInFailure::InvalidUsername) { usernameOf(username) } },
{ withError(LogInFailure::InvalidPassword) { passwordOf(password) } },
::Pair)
…further processing…
}
simon.vergauwen
03/26/2024, 8:15 AM(A, B, (A,B) -> C) -> C
and (A, B, C) -> Triple
signature.
It confuses these two, and they don't resolve without explicitly "selecting" with like explicit param names, or something.
So since it cannot be naturally overloaded we decided not to add zipOrAccumulateTuple
in favor of ::Triple
.Alejandro Serrano.Mena
03/26/2024, 9:05 AM@OverloadByReturnLambda
annotation for this, but in my experience it fails quite often.
We considered having versions like zipOrAccumulatePair
, but at the end of the day these are not more characters than zipOrAccumulate(...., ..., ::Pair)
simon.vergauwen
03/26/2024, 9:07 AM::Triple
doesn't "fit" into suspend CoroutineScope.(A, B, C) -> D
. (parMap
, etc. Don't think it's an issue here).
It should fit, but an unused extension receivers is currently not automatically ignored. Would that be fixed with context(CoroutineScope)
? And does that refactor break the binary signature? 🤔 (Sorry, some of these questions only come up naturally 😅)
Also, don't think this is about @OverloadByReturnLambda
since Kotlin cannot understand the difference between C
and (A, B) -> C
. Should be unrelated to the lambda return type, right? 🤔Alejandro Serrano.Mena
03/26/2024, 9:08 AMsimon.vergauwen
03/26/2024, 9:11 AMcontext
can be "ignored" than it solves my problem TBH.
It fixes it 100% if context
won't break the binary compat (same ordering of of params), because then it kind-of makes sense that an explicit receiver is not ignored but an "implicit" (?) one can be ignored. Similar train of thought as scope pollution of buidList
.CLOVIS
03/26/2024, 9:41 AMfun logIn(username: String, password: String) = either {
val (validUsername, validPassword) = Accumulate
.withError(LogInFailure::InvalidUsername) { usernameOf(username) }
.withError(LogInFailure::InvalidPassword) { passwordOf(password) }
.bind()
}
This would be much more convenient to work with for end users because auto-complete would be much less a mess (understanding the signature of the dozen variants of zipOrAccumulate
is… a challenge). The main downside is it requires creating n
intermediary result types to have type-safety for the return values 😕 Or maybe TupleXX
can be reused.Kev
03/26/2024, 10:35 AMCLOVIS
03/26/2024, 10:36 AM