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的博客

  • 相关阅读:
    unityshader(属性)
    unity_实用小技巧(相机跟随两个主角移动)
    unity_实用小技巧(空指针错误)
    unity_实用小技巧(避免游戏对象被销毁时声音消失)
    php把网络图片转Base64编码。(php将图片链接直接转化为base64编码)
    TP5.0 where数组高级查询
    使用Guzzle执行HTTP请求
    JWT实战:使用axios+PHP实现登录认证
    有关JWT(Json Web Token)的那些事
    thinkphp5一键清除缓存
  • 原文地址:https://www.cnblogs.com/flydean/p/12680349.html
Copyright © 2011-2022 走看看