Chaining方法使用Either调用 [英] Chaining method calls with Either

查看:116
本文介绍了Chaining方法使用Either调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以创建某种方法调用链,所有方法都返回相同的[Error,Result]。



我想要做的是:连续调用所有方法,当方法返回一个Left(Error)时,停止方法调用并返回调用链中找到的第一个Left。



我尝试了一些东西,包括折叠,地图,投影......但我是新来的Scala,没有找到任何优雅的解决方案。



我尝试了一些这样的事情:

  def createUserAndMandatoryCategories(user:User):[Error,用户] = {
User.create(user).right.map {
Logger.info(User created)
Category.create(Category.buildRootCategory(user)).right。 map {
Logger.info(根类别创建)
Category.create(Category.buildInboxCategory(用户)).right.map {
Logger.info(Inbox category created
Category.create(Categ ory.buildPeopleCategory(user)).right.map {
Logger.info(People category created)
Category.create(Category.buildTrashCategory(user)).right.map {
Logger.info(创建垃圾类别)
Logger.info(所有类别创建成功)
正确(用户)
}
}
}
}
}
}

但它不起作用。
无论如何,我真的不喜欢它需要的缩进。
除此之外,我想将错误转换为一个描述问题的新字符串(我想我应该使用fold?)

我正在寻找一些东西这样写:

  val结果:或者[String,CallResult] = call1.something(error 1 description)
.call2.something(error 2 description)
.call3.something(error 3 description)
.call4.something(error 4 description)

有可能用Scala做这样的事情吗?也许同时使用Either和Option?



一个约束条件是,如果第一次呼叫失败,则不应进行其他呼叫。我不想要一个解决方案,我打电话给所有人,然后加入他们。



谢谢!

解决方案

有更好,更实用的方法来做到这一点(主要涉及斯卡拉斯的验证和遍历/序列),但您的代码大致相当于:

  def createUserAndMandatoryCategories(user:User):或者[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

至少可以摆脱所有的嵌套。由于Scala的 默认情况下不是正确的偏见,所以您必须手动指定这几次,这会降低可读性。


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.

这篇关于Chaining方法使用Either调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆