dreamreal
07/04/2023, 2:27 PMreturn runBlocking {
var localContainer = container;
operators.forEach {
localContainer = it.apply(localContainer)
}
localContainer
}
(after all, each operator can do IO to load additional state or whatever, and it’s okay if that takes a while.)
However:
1. What’s a more Kotlin way to do this? I keep thinking I should use a Result
for this.
2. localContainer
is, at the end of the exception, the original argument, and not the container value at the point of the exception; why?Chris Lee
07/04/2023, 2:31 PMoperations.fold(container) { it.apply(container) }
dreamreal
07/04/2023, 2:32 PMdreamreal
07/04/2023, 2:32 PMChris Lee
07/04/2023, 2:33 PMdreamreal
07/04/2023, 2:34 PMdreamreal
07/04/2023, 2:34 PMreturn operators.fold(container) { c,operator -> operator.apply(c)}
dreamreal
07/04/2023, 2:35 PMChris Lee
07/04/2023, 2:35 PMdreamreal
07/04/2023, 2:35 PMdreamreal
07/04/2023, 2:36 PMChris Lee
07/04/2023, 2:36 PMdreamreal
07/04/2023, 2:37 PMdreamreal
07/04/2023, 2:39 PMdreamreal
07/04/2023, 2:39 PMdreamreal
07/04/2023, 2:40 PMdreamreal
07/04/2023, 2:41 PMdreamreal
07/04/2023, 2:42 PMdreamreal
07/04/2023, 2:45 PMJacob
07/04/2023, 2:47 PMdreamreal
07/04/2023, 2:47 PMdreamreal
07/04/2023, 2:47 PMJacob
07/04/2023, 2:47 PMdreamreal
07/04/2023, 2:47 PMdreamreal
07/04/2023, 2:47 PMdreamreal
07/04/2023, 2:48 PMChris Lee
07/04/2023, 2:49 PMdreamreal
07/04/2023, 2:50 PMJacob
07/04/2023, 2:50 PMChris Lee
07/04/2023, 2:51 PMpublic sealed class ClaimVerificationResult {
public class Failure(private val claimName: String, private val message: String) : ClaimVerificationResult() {
override fun toString(): String = "JWT Claim '$claimName' $message"
}
public data object Success : ClaimVerificationResult()
}
…that’s a fairly simple one. More complicated cases would have a richer type hierarchy to operate on.dreamreal
07/04/2023, 2:52 PMdreamreal
07/04/2023, 2:52 PMYonatan Karp-Rudin
07/04/2023, 2:53 PMChris Lee
07/04/2023, 2:53 PMClaimVerificatinResult
and the outer could would do a when
on the result looking at the type and processing accordingly.dreamreal
07/04/2023, 2:53 PMdreamreal
07/04/2023, 2:54 PMYonatan Karp-Rudin
07/04/2023, 2:56 PMdreamreal
07/04/2023, 2:57 PMChris Lee
07/04/2023, 2:57 PMreturn c.copy(events = e)
all good there, objects remain immutable.Yonatan Karp-Rudin
07/04/2023, 2:57 PMdreamreal
07/04/2023, 2:57 PMYonatan Karp-Rudin
07/04/2023, 2:59 PMdreamreal
07/04/2023, 2:59 PMYonatan Karp-Rudin
07/04/2023, 2:59 PMYonatan Karp-Rudin
07/04/2023, 3:00 PMdreamreal
07/04/2023, 3:01 PMdreamreal
07/04/2023, 3:01 PMChris Lee
07/04/2023, 3:08 PMinterface Operator2 {
suspend fun apply(c: Container): OperatorResult
}
sealed class OperatorResult(val container : Container) {
data class Success(container : Container) : OperatorResult(container)
data class Failure(val lastContainer : Container, val message : String) : OperatorResult(lastContainer)
}
class Machine2() {
suspend fun execute(
container: Container,
operators: List<Operator2>
): Container {
// start with Success and keep processing until failure, return container
// alternately this could be operators.map to transform each into a result and then process from there
return operators.fold(Success(container)) { result, operator ->
when(result) {
is Failure -> result.container
else -> operator.apply(result.container)
}
}
}
}
Jacob
07/05/2023, 1:48 AM