本文介绍了在 Scala 中使用 andThen 链接 PartialFunctions的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们重用 Daily scala 中的示例:

Let us reuse examples from Daily scala :

type PF = PartialFunction[Int,Int]

val pf1 : PF = {case 1 => 2}

val pf2 : PF = {case 2 => 3}

让我们补充:

val pf3 : PF = {case 3 => 4}

andThen 在这里按预期工作:

andThen works as expected here:

pf1 andThen pf2 isDefinedAt(x)

返回 true iff x == 1(实际上,pf2 根本不需要是 PartialFunction)

returns true iff x == 1 (actually, pf2 does not need to be a PartialFunction at all)

但是,我预计:

pf1 andThen pf3 isDefinedAt(x)

将为所有 x 返回 false(即,如果定义了 pf1,检查 pf3),但它不会且仅验证 pf1.

would return false for all x (i.e., iff pf1 is defined, check for pf3), but it does not and only validates pf1.

最后,pf1 andThen pf3 lift(x) 总是导致MatchError.我宁愿得到 None ......我可以通过提升每个函数来获得这种行为,例如 pf1.lift(x).flatMap(pf3.lift) 但是有没有更简单的方法使用纯 PartialFunction API?(并且没有单独提升每个部分功能?)

In the end, pf1 andThen pf3 lift(x) always result in a MatchError. I would prefer to get None… I can obtain this behavior by lifting each function such as in pf1.lift(x).flatMap(pf3.lift) but is there any easier way using pure PartialFunction API? (and without lifting each partial function individually?)

推荐答案

如果你看andThen:

def andThen[C](k: (B) => C): PartialFunction[A, C]

这将接收器与函数而不是部分函数组合在一起.也就是说,k 应该是完全定义的,它没有 isDefinedAt.因此,生成的偏函数不需要改变 isDefinedAt 的行为,它仍然只需要参考第一个偏函数.

This composes the receiver with a function and not a partial function. That is, k is expected to be fully defined, it doesn't have isDefinedAt. Therefore, the resulting partial function does not need to alter the behaviour of isDefinedAt, it will still just has to consult the first partial function.

您可以编写自己的包含两个部分函数的扩展:

You could write your own extension that composes two partial functions:

implicit class ComposePartial[A, B](pf: PartialFunction[A, B]) {
  def collect[C](that: PartialFunction[B, C]): PartialFunction[A, C] =
    new PartialFunction[A, C] {
      def apply(a: A): C = that(pf(a))
      def isDefinedAt(a: A) = pf.isDefinedAt(a) && {
        val b = pf(a)
        that.isDefinedAt(b)
      }
    }
}

pf1 collect pf2 isDefinedAt(1)  // true
pf1 collect pf3 isDefinedAt(1)  // false

问题在于您必须调用 pf(a),因此鉴于 Scala 不强制执行纯度,您最终可能会意外地执行副作用.

The problem is that you have to invoke pf(a), so given that Scala doesn't enforce purity, you may end up executing side effects unwantedly.

这篇关于在 Scala 中使用 andThen 链接 PartialFunctions的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-14 08:45