zoukankan      html  css  js  c++  java
  • 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.Float, scala.Long, 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的博客

  • 相关阅读:
    使用session页面控制登录入口及购物车效果的实现
    php中会话保持 session 与cooker
    php多关键字查询
    php后台编辑关联数据
    php后台增删改跳转
    php登录注册页面及加载
    [bzoj4098] [Usaco2015 Open]Palindromic Paths
    [bzoj1969] [Ahoi2005]LANE 航线规划
    4395: [Usaco2015 dec]Switching on the Lights
    [bzoj2789] [Poi2012]Letters
  • 原文地址:https://www.cnblogs.com/flydean/p/12680349.html
Copyright © 2011-2022 走看看