I am looking for a way to combine several validati...
# arrow
u
I am looking for a way to combine several validation errors using the raise DSL when there is no result to return. While there is
forEachAccumulating
instead of
mapOrAccumulate
when I am only interested in the errors, there does not seem to be a similarly complementarey function to
zipOrAccumulate
, is there? What I suppose I need is something along those lines:
Copy code
fun RaiseAccumulate<MyError>.ensureIsValid(myIdString: String) =
        ensureAccumulate( // this function does not exist
            { ensure( someCondition1(myIdString) ) { IncorrectCondition1(myIdString) } },
            { ensure( Dsomecondition2(myIdString) ) { IncorrectCondition2(myIdString) } }
        )
a
at this moment, unfortunately you need to write something along the lines of
Copy code
zipOrAccumulate(
  { ensure(...) }
  { ensure(...) }
) { }
however, in the 2.0 to be released soon, you've be able to write much nicer code
Copy code
accumulate {
  ensureAccumulating(thing1) { ... }
  ensureAccumulating(thing2) { ... }
}
👍 1
🎉 1
🚀 1
r
Wow! That's great! I'm curious: what’s the returning type of the
ensureAccumulating
function? I mean, in case of an error, you need to return something to let the execution proceed
a
just
Unit
r
Ok. The semantic is different from
zipOrAccumulate
then. You can’t return a valid object as the return of the
accumulate
function. Did I get it wrong?
a
no, you definitely can. The DSL in that case encourages using delegated properties
Copy code
accumulate {
  val name by validateName(rawName).bindOrAccumulate()
  val age by validateAge(rawAge).bindOrAccumulate()
  Person(name, age)
}
mind blown 1
r
Thanks, Alejandro 🙏. I need to check the implementation to understand it better. By the way, it’s a nice DSL improvement 🙌
a
the main "trick" is that by using delegated properties we can delay the "bind" aspect to the moment in which the first variable is read. The code above actually compiles under the hood to:
Copy code
accumulate {
  val name: Value<Name> = validateName(rawName).bindOrAccumulate()
  val age: Value<Age> = validateAge(rawAge).bindOrAccumulate()
  Person(name.getValue(), age.getValue())
}
during the
bindOrAccumulate
(or any other accumulation function) we simply accumulate any errors in a temporary list. In the first call to
getValue()
we check that list, and it's there's something, we just raise the corresponding set of errors. unfortunately this is something which drinks a lot from Kotlin's delegated properties feature; I'm sure you can transpose it to Swift, but I'm not so sure about other languages...
arrow intensifies 1
K 1
gratitude thank you 1
r
but I’m not so sure about other languages...
In fact, I was thinking about how to transpose it into Scala 😅 By the way, big shout-out 👏