Scala教程之:PartialFunction

Scala中有一个很有用的traits叫PartialFunction,我看了下别人的翻译叫做偏函数,但是我觉得部分函数更加确切。

那么PartialFunction是做什么用的呢?简单点说PartialFunction用在模式匹配中,是一个不完整的函数,它只实现了函数的部分功能,也就是列举了部分case的情况。

我们先看下PartialFunction的定义:

trait PartialFunction[-A,+B] extends (A => B) { 
    ...

 def isDefinedAt(x: A): Boolean

    ...

我们可以看到PartialFunction是一个trait,它继承自函数 (A => B), 这个函数有一个参数和一个返回值,在Scala中,该函数会被自动解析为Function1。

我们看下Function1的定义:

trait Function1[@specialized(scala.Int,scala.Long,scala.Float,scala.Double) -T1,@specialized(scala.Unit,scala.Boolean,scala.Int,scala.Double) +R] extends AnyRef { self =>
  /** Apply the body of this function to the argument.
   *  @return   the result of function application.
   */
  def apply(v1: T1): R

我们可以看到Function1定义了一个方法: def apply(v1: T1): R

PartialFunction也定义了一个方法: def isDefinedAt(x: A): Boolean

如果我们要自己实现一个PartialFunction,则必须实现上述两个方法:

  val inc = new PartialFunction[Any,Int] {
    override def isDefinedAt(x: Any): Boolean = ???

    override def apply(v1: Any): Int = ???
  }

其中isDefinedAt用来选择PartialFunction入参的范围,而apply是真正的业务逻辑。

除了用new来实例化一个PartialFunction外,还有一个最简单的方法就是使用case语句。 我们举个例子, 如果我们有段case逻辑是匹配各个好吃等级,如下:

  println("Step 1: Review of Pattern Matching in Scala")
  val donut = "Glazed Donut"
  val tasteLevel = donut match {
    case "Glazed Donut" | "Strawberry Donut" => "Very tasty"
    case "Plain Donut" => "Tasty"
    case _  => "Tasty"
  }
  println(s"Taste level of $donut = $tasteLevel")

我们使用了3个case语句,看起来比较繁琐,使用PartialFunction, 我们可以将其转换为如下的形式:

  val donutTaste = isVeryTasty orElse isTasty orElse unknownTaste
  println(donutTaste("Glazed Donut"))
  println(donutTaste("Plain Donut"))
  println(donutTaste("Chocolate Donut"))

PartialFunction可以通过使用orElse关键字来合并成一个完整的Function。

我们看下这几个PartialFunction该怎么定义:

  val isVeryTasty: PartialFunction[String,String] = {
    case "Glazed Donut" | "Strawberry Donut" => "Very Tasty"
  }

  val isTasty: PartialFunction[String,String] = {
    case "Plain Donut" => "Tasty"
  }

  val unknownTaste: PartialFunction[String,String] = {
    case donut1 @ _ => s"Unknown taste for donut = $donut1"
  }

实际上就是把整个的业务逻辑,用PartialFunction拆分开来了。这里使用case语句,会自动转换成为PartialFunction。

关注下最后一个unknownTaste的case语句, @ 使用来做模式匹配的, case donut1 @ _ 就意味着 donut1 将会匹配所有的输入。

更多教程请参考 flydean的博客

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...