我有一个密封的特点,其实施由3个对象

sealed trait MyTrait {
...
}
object A extends MyTrait { ... }
object B extends MyTrait { ... }
object C extends MyTrait { ... }

我使用的Scalaz的验证机制,其中适用方法的目的A、B和C返回经过验证的类型。的对象,A、B和C不包含一些逻辑和我想要应用这种逻辑顺序,即,我想首先应用和检查什么样的结果是,在此基础上,决定如果我想打电话给B,或只是返回的经过验证的结果。我想重复这个直到我打C在这之后我只是回不管我获得作为结果的调C.

目前,我有一个静态的办法在那里我第一个电话,将结果传递到一个实用的方法和检查的结果,然后打电话给B。

  def apply(request: Request): Validated[Result] = {
    val vResultA = run(request, A)
    val vResultB = if (isResultOk(vResultA)) run(request, B) else vResultA
    if (isResultOk(vResultB)) run(request, C) else vResultB
  }

有没有更好的方式做到这一点?任何建议或任何模式,我可以申请吗?

有帮助吗?

解决方案

我们将定义 成功的结果=的结果都确定, , 失败的结果=的结果,是不确定.

第一, A, B, , C 是所有物体的延伸 MyTrait.因此,他们可以分为一系列或一个列表中的 MyTrait.

val objects = Array(A, B, C) /* You can use List instead if you want. */

那类型的 objectsArray[MyTrait].

接下来,我们必须迭代,在这个阵列。
然而,只是打电话 map 在这个阵列的继续射即使以前的 isResultOk()false.
因此,我们将使用 Stream 而不是的 Array.

让我们看看如何使用 Stream 可以停止调用 map 如果某些条件得到满足。

Array(1, 2, 3, 4, 5).map(i => {
    println(i)
    i + 100
  }).takeWhile(_ <= 103).foreach(println(_))

输出的上述码将是:

1
2
3
4
5
101
102
103

所以, map() 结束,然后 takeWhile() 结束-- takeWhile() 并不影响叫 map().
然而,如果我们做同样的操作 Stream,

Array(1, 2, 3, 4, 5).toStream.map(i => {
    println(i)
    i + 100
  }).takeWhile(_ <= 103).foreach(println(_))

输出将是:

1
101
2
102
3
103
4

因此呼吁会 map() -> takeWhile() -> foreach() -> map() -> takeWhile() -> ...
在结束、4印刷和4+100=104>103将切 takeWhile().
以下要素将是不访问进一步。

因此,我们必须使用takeWhile?

objects.toStream.map(run(request, _)).takeWhile(isResultOk(_))

这将摆脱失败的结果,尽管我们需要第一个失败的结果,如果未发生。
(即这将使一个问题,如果有任何结果,是不确定。)

关于如何相反的功能 dropWhile()?

objects.toStream.map(run(request, _)).dropWhile(isResultOk(_))

这将摆脱所有成功的结果,即使所有结果都取得了成功。
(即这将使一个问题,如果所有的结果都确定。)

因此,我们将使用 span().
c.span(p) = (c.takeWhile(p), c.dropWhile(p))
我们将测试,如果有结果都是不确定。
如果有一个结果,是不确定,然后我们将返回的第一个这样的结果。
否则,我们将返回的最后结果,该结果确定。

val (succ, fail) = objects.toStream.map(run(request, _)).span(isResultOk(_))
fail.headOption.getOrElse(succ.last)

fail.headOption 将返回 Some(fail's first element) 如果 fail 不是空的,否则 None.

在摘要,

val objects = Array(A, B, C)

def apply(request: Request): Validated[Result] = {
  val (succ, fail) = objects.toStream.map(run(request, _)).span(isResultOk(_))
  fail.headOption.getOrElse(succ.last)
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top