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