I'd like to know if it is possible to create some kind of "method call chain", with all methods returning the same Either[Error,Result].
What i'd like to do is: call all the methods successively, and when method returns a Left(Error), then stop the method calls and return the first Left found in the call chain.
I've tryied some stuff, with fold, map, projections... but i'm new to Scala and don't find any elegant solution.
I've tryed some thing like that:
def createUserAndMandatoryCategories(user: User) : Either[Error,User] = {
User.create(user).right.map {
Logger.info("User created")
Category.create( Category.buildRootCategory(user) ).right.map {
Logger.info("Root category created")
Category.create( Category.buildInboxCategory(user) ).right.map {
Logger.info("Inbox category created")
Category.create( Category.buildPeopleCategory(user) ).right.map {
Logger.info("People category created")
Category.create( Category.buildTrashCategory(user) ).right.map {
Logger.info("Trash category created")
Logger.info("All categories successfully created created")
Right(user)
}
}
}
}
}
}
But it doesn't work. And anyway i really don't like the indentation it takes. Besides i'd like to transform the Error into a new String describing the problem (i guess i should use fold?)
I'm looking for something written like that:
val result : Either[String,CallResult] = call1.something("error 1 description")
.call2.something("error 2 description")
.call3.something("error 3 description")
.call4.something("error 4 description")
Is it possible to do such a thing with Scala? Perhaps using both Either and Option?
One constraint would also be that if the first call fails, the other calls should not be made. I don't want a solution where i call everything and then join the eithers.
Thanks!
There are better, more functional ways to do this (mostly involving Scalaz’s Validation and traverse/sequence) but your code is roughly equivalent to:
def createUserAndMandatoryCategories(user: User) : Either[Error,User] = for {
_ <- User.create(user).right.map(Logger.info("User created")).right
_ <- Category.create( Category.buildRootCategory(user) ).right.map(Logger.info("Root category created")).right
_ <- Category.create( Category.buildInboxCategory(user) ).right.map(Logger.info("Inbox category created")).right
} yield user
Which at least gets rid of all the nesting. Since Scala’s Either
is not right-biased by default, you have to specify that manually quite a few times, which reduces the readability a bit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With