Fred Friis
08/19/2020, 4:32 AM//given
private fun getUserRole(user: User): Either<IError, SearchUserResponse> {
}
//this generates an explosion of calls
users
.asSequence()
.map { getUserRole(it) }
.sequence(Either.applicative())
.map { it.fix() }
.map { it.toSortedSet(comparator) }
//all we want is to call getUserRole one by one
//AND short circuit on the first error
//ie if there's 100 users and we get an error on
//the 2nd one, we don't want to call getUserRole
//another 98 times
simon.vergauwen
08/19/2020, 6:29 AMusers.traverse(Either.applicative()) { user ->
getUserRole(user)
}.map { it.fix().toSortedSet(comparator) }
I'm assuming users
is of type Set
? If it's of type Set
then you need to first convert to a data type that guarantees order, or won't discard results like Set
does.simon.vergauwen
08/19/2020, 6:30 AMtraverse
is like sequence
but it combines itself with the map
operation, so that you can do.
List<User> -> Either<IError, List<SearchUserResponse>
with a single function call.simon.vergauwen
08/19/2020, 6:32 AM0.11.0-SNAPSHOT
you could also simply do the following:
either {
users.map { !getUserRole(it) }
.toSortedSet(comparator)
}
Here !
will short-circuit on the first Left
as well, returning it's IError
.Jannis
08/19/2020, 12:18 PMtraverse
evaluated all elements of a sequence before it short-circuits. It should be fixed traverse/sequence
or just straight up use the either
dsl and any inline function.
If you don't want to upgrade you can probably also use the normal eitherfx
dsl if sequence map is inline Either.fx { seq.map { stuff().bind() } }
.Jannis
08/19/2020, 12:38 PMFred Friis
08/19/2020, 11:12 PM