# Scala 函數

原文鏈接:https://www.runoob.com/scala/currying-functions.html

Scala 函數傳名調用(call-by-name)

Scala的解釋器在解析函數參數(function arguments)時有兩種方式:

  • 傳值調用(call-by-value):先計算參數表達式的值,再應用到函數內部;
  • 傳名調用(call-by-name):將未計算的參數表達式直接應用到函數內部

在進入函數內部前,傳值調用方式就已經將參數表達式的值計算完畢,而傳名調用是在函數內部進行參數表達式的值計算的。

這就造成了一種現象,每次使用傳名調用時,解釋器都會計算一次表達式的值。

object Test{
    
    val f = (x: Int) => x+3
    def m(x:Int) = x + 3 
	def main(args:Array[String]){
		delayed(time())
	}
	
	def time() = {
		println("獲取時間,單位爲納秒")
		System.nanoTime
	}
	
	def delayed(t: => Long) {  // 使用=> 符號來設置傳名調用
	   println("在 delayed 方法內")
       println("參數: " + t)
       t
	}
	
}

指定函數參數名

一般情況下函數調用參數,就按照函數定義時的參數順序一個個傳遞。但是我們也可以通過指定函數參數名,並且不需要按照順序向函數傳遞參數,實例如下:

object Test {
  def main(args: Array[String]) {
    printInt(b = 5, a = 7)
  }

  def printInt(a:Int,b:Int) = {
    println("Value of a : " + a)
    println("Value of b : " + b)
  }
}

運行結果:
Value of a : 7
Value of b : 5

可變參數

Scala 允許你指明函數的最後一個參數可以是重複的,即我們不需要指定函數參數的個數,可以向函數傳入可變長度參數列表。

Scala 通過在參數的類型之後放一個星號來設置可變參數(可重複的參數)。例如:

object Test {
   def main(args: Array[String]) {
        printStrings("Runoob", "Scala", "Python");
   }
   def printStrings( args:String* ) = {
      var i : Int = 0;
      for( arg <- args ){
         println("Arg value[" + i + "] = " + arg );
         i = i + 1;
      }
   }
}

高階函數

高階函數就是操作其他函數的函數

Scala 中允許使用高階函數,高階函數可以使用其他函數作爲參數,活着使用函數作爲輸出結果

以下實例中,apply() 函數使用了另外一個函數 f 和 值 v 作爲參數,而函數 f 又調用了參數 v:

object Test {
  def main(args: Array[String]) {
    println(apply(layout, 10))
  }

  def apply(f: Int => String, v: Int) = f(v)

  def layout[A](x: A) = "[" + x.toString + "]"
}

函數嵌套

我們可以在Scala 函數內定義函數,定義在函數內部的函數稱爲局部函數

object Test {
  def main(args: Array[String]) {
    println( factorial(0) )
    println( factorial(1) )
    println( factorial(2) )
    println( factorial(3) )
  }

  def factorial(i: Int): Int = {
    def fact(i: Int, accumulator: Int): Int = {
      if (i <= 1) {
        accumulator
      } else {
        fact(i - 1, i * accumulator)
      }
    }

    fact(i, 1)
  }
}

匿名函數

Scala 中定義匿名函數很簡單,箭頭左邊是參數列表,右邊是函數體

var inc =(x:Int) => x+2
var x = inc(7)-1
var mul = (x:Int,y:Int) => x * y
println(mul(3, 4))

object Demo {
   def main(args: Array[String]) {
      println( "multiplier(1) value = " +  multiplier(1) )
      println( "multiplier(2) value = " +  multiplier(2) )
   }
   var factor = 3
   val multiplier = (i:Int) => i * factor
}

Scala 偏應用函數

Scala 偏函數是一種表達式,不需要提供行數的所有參數,只需要部分參數,或不需要參數

import java.util.Date

object Test {
   def main(args: Array[String]) {
      val date = new Date
      log(date, "message1" )
      Thread.sleep(1000)
      log(date, "message2" )
      Thread.sleep(1000)
      log(date, "message3" )
   }

   def log(date: Date, message: String)  = {
     println(date + "----" + message)
   }
}


import java.util.Date

object Test {
  def main(args: Array[String]) {
    val date = new Date
    val logWithDateBound = log(date, _ : String) //第二個參數使用下劃線(_)替換缺失的參數列表,並把這個新的函數值的索引的賦給變量。

    logWithDateBound("message1" )
    Thread.sleep(1000)
    logWithDateBound("message2" )
    Thread.sleep(1000)
    logWithDateBound("message3" )
  }

  def log(date: Date, message: String)  = {
    println(date + "----" + message)
  }
}

柯里化函數

柯里化(Currying)指的是將原來接收倆個參數的行數編程了接收一個參數函數的過程。新的函數返回一個以原有第二個參數爲參數的函數。

object Test {
   def main(args: Array[String]) {
      val str1:String = "Hello, "
      val str2:String = "Scala!"
      println( "str1 + str2 = " +  strcat(str1)(str2) )
   }

   def strcat(s1: String)(s2: String) = {
      s1 + s2
   }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章