Scala 函數

一、Scala偏函數(PartialFunction)app

    1.1 它之因此偏,是由於它並不處理全部可能的輸入,而只處理那些能與至少一個case語句匹配的輸入。在偏函數中,只能使用case語句,而整個函數必須用花括號包圍。這與普通的函數字面量不一樣,普通的字面量既能夠用花括號,也能夠用圓括號包圍。函數

    1.2 偏函數定義:def 函數名:PartialFunction[輸入類型, 輸出類型] = { case ... => ... }測試

    1.3 偏函數能夠鏈式,如 pf1 orElse pf2 orElse pf3 ...若是pf1不匹配則匹配pf2,再不匹配則匹配pf3,以此類推。若都不知足,則拋出scala.MatchError。this

  1.4 使用isDefinedAt(x: A): Boolean方法來判斷測試特定的輸入是否與偏函數匹配,避免scala.MatchErrorscala

    1.5 scala程序設計樣例:設計

def cat(s1:String)(s2:String) = s1 + s2

  /**
    * val hello = cat("Hello ")
    * hello("World")
    * 以上調用方式會拋出以下異常:
    * Error:(34, 18) missing argument list for method cat in object TestCase
    * Unapplied methods are only converted to functions when a function type is expected.
    * You can make this conversion explicit by writing `cat _` or `cat(_)(_)` instead of `cat`.
    */
    //調用方式1:
    val hello = cat("Hello ") _ //注意下劃線(_)
    hello("World")  //Hello World
    //調用方式2:
    cat("Hello ")("World")  //Hello World

    1.6 Spark源碼樣例:code

/**
   * Process messages from [[RpcEndpointRef.send]] or [[RpcCallContext.reply)]]. If receiving a
   * unmatched message, [[SparkException]] will be thrown and sent to `onError`.
   */
  def receive: PartialFunction[Any, Unit] = {
    case _ => throw new SparkException(self + " does not implement 'receive'")
  }

  /**
   * Process messages from [[RpcEndpointRef.ask]]. If receiving a unmatched message,
   * [[SparkException]] will be thrown and sent to `onError`.
   */
  def receiveAndReply(context: RpcCallContext): PartialFunction[Any, Unit] = {
    case _ => context.sendFailure(new SparkException(self + " won't reply anything"))
  }

二、Curry化ci

    2.1 Curry講一個帶有多個參數的函數轉換爲一系列函數,每一個函數都只有一個參數。源碼

    2.2 Scala程序設計樣例:it

//def cat(s1:String)(s2:String) = s1 + s2
  //上述函數改寫爲Curry
  def cat(s1:String) = (s2:String) => s1 + s2
  val hello = cat("Hello ") //注意此處沒有下劃線(_)
  hello("World")  //Hello World
  //調用方式2:
  cat("Hello ")("World")  //Hello World

三、函數參數的調用方式:call-by-value與call-by-name

    3.1 call-by-value:傳給函數的參數是個值,若是是個表達式或者是另一個參數函數,則要先計算出表達式的值或者是要先獲得參數函數執行後的返回值

/**
    * call-by-value
    * 不會輸出begin...,直接拋出異常
    * @param p  注意函數參數的定義無(=>)
    */
  def callByValue(p:Boolean) = {
    println("begin...")
    p
    println("end...")
  }
  callByValue(1 / 0 == 0)

    3.2 call-by-name:傳給函數方法的參數是另一個參數函數,該參數函數在函數體內調用時執行

/**
    * call-by-name
    * 會先輸出begin...,在拋出異常
    * @param p  注意函數參數的定義有一個(=>)
    */
  def callByName(p: => Boolean) = {
    println("begin...")
    p
    println("end...")
  }
  callByName(1 / 0 == 0
  
  //等效於
  def callByName(p:() => Boolean) = {
    println("begin...")
    p() //注意必須有圓括號
    println("end...")
  }
  callByName(() => 1 / 0 == 0)
相關文章
相關標籤/搜索