# Scala中的偏函数

```trait PartialFunction[-A, +B] extends (A => B) { self =>
import PartialFunction._
def isDefinedAt(x: A): Boolean
def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 =
if (isDefinedAt(x)) apply(x) else default(x)
}```

`val p:PartialFunction[Int, String] = { case 1 => "One" }`

`def isDefineAt(x: Int):Boolean = x == 1`

```abstract class AbstractPartialFunction[
@specialized(scala.Int, scala.Long, scala.Float, scala.Double, scala.AnyRef) -T1,
@specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double, scala.AnyRef) +R]
extends Function1[T1, R] with PartialFunction[T1, R] { self =>
def apply(x: T1): R = applyOrElse(x, PartialFunction.empty)
}```

apply()方法内部调用了PartialFunction的applyOrElse()方法。若isDefineAt(x)返回为false，就会将x值传递给PartialFunction.empty。这个empty等于类型为PartialFunction[Any, Nothong]的值empty_pf，定义如下：

```  private[this] val empty_pf: PartialFunction[Any, Nothing] = new PartialFunction[Any, Nothing] {
def isDefinedAt(x: Any) = false
def apply(x: Any) = throw new MatchError(x)
override def orElse[A1, B1](that: PartialFunction[A1, B1]) = that
override def andThen[C](k: Nothing => C) = this
override val lift = (x: Any) => None
override def runWith[U](action: Nothing => U) = constFalse
}```

```val positiveNumber:PartialFunction[Int, Int] = {
case x if x > 0 => x
}
val zero:PartialFunction[Int, Int] = {
case x if x == 0 => 0
}
val negativeNumber:PartialFunction[Int, Int] = {
case x if x < 0 => -x
}
def abs(x: Int): Int = {
(positiveNumber orElse zero orElse negativeNumber)(x)
}```

```val pf: PartialFunction[Int, String] = {
case i if i%2 == 0 => "even"
}
val tf: (Int => String) = pf orElse { case _ => "odd" }```

orElse被定义在PartialFunction类型中，而andThen与compose却不同，它们实则被定义在Function中，PartialFunction只是重写了这两个方法。这意味着函数之间的组合可以使用andThen与compose，偏函数也可以。这两个方法的功能都是将多个（偏）函数组合起来形成一个新函数，只是组合的顺序不同，andThen是组合第一个，接着是第二个，依次类推；而compose则顺序相反。

```trait PartialFunction[-A, +B] extends (A => B) {
override def andThen[C](k: B => C): PartialFunction[A, C] =
new AndThen[A, B, C] (this, k)
}
object PartialFunction {
private class AndThen[-A, B, +C] (pf: PartialFunction[A, B], k: B => C) extends PartialFunction[A, C] {
def isDefinedAt(x: A) = pf.isDefinedAt(x)
def apply(x: A): C = k(pf(x))
override def applyOrElse[A1 <: A, C1 >: C](x: A1, default: A1 => C1): C1 = {
val z = pf.applyOrElse(x, checkFallback[B])
if (!fallbackOccurred(z)) k(z) else default(x)
}
}
}```

```val p1:PartialFunction[String, String] = {
case s if s.contains("1") => s.replace("1", "one")
}
val p2:PartialFunction[String, String] = {
case s if s.contains("2") => s.replace("2", "two")
}
val p = p1 andThen p2```

```val forHKG:PartialFunction[Market, List[TaxFee]] = ...
val forSGP:PartialFunction[Market, List[TaxFee]] = ...
val forAll:PartialFunction[Market, List[TaxFee]] = ...

```trait Publisher[T] {
def subscribe(f: PartialFunction[T, Unit])
}
val publisher: Publisher[Int] = ...

publisher.subscribe {
case i if isPrime(i) => println("found prime", i)
case i if i%2 == 0 => count += 2
/* ignore the rest */
}```

```trait Actor {
}
object Actor {
}```

```val sample = 1 to 10
sample map {
case x if x % 2 == 0 => x + " is even"
case x if x % 2 == 1 => x + " is odd"
}```

```//avoid
list map { item =>
item match {
case Some(x) => x
case None => default
}
}
//recommend
list map {
case Some(x) => x
case None => default
}```

164 篇文章43 人订阅

0 条评论

## 相关文章

13940

32720

### 第172天：面向对象基本知识点

2 .构造函数内部会创建一个新的对象，即f的实例

9530

### 用js来实现那些数据结构08（链表02-双向链表）

其实无论在任何语言中，一种数据结构往往会有很多的延伸和变种以应对不同场景的需要。其实前面我们所学过的栈和队列也是可以用链表来实现的。有兴趣的小伙伴可以自己尝...

31360

498220

40590

34450

### Java基础01 从HelloWorld到面向对象

Java是完全面向对象的语言。Java通过虚拟机的运行机制，实现“跨平台”的理念。我在这里想要呈现一个适合初学者的教程，希望对大家有用。

10010

### c语言基础学习09_复合类型

============================================================================= 涉及...

18810

14500