Scala函数声明具备如下形式 -java
def functionName ([list of parameters]) : [return type]
若是不使用等号和方法体,则隐式声明抽象(abstract
)方法。程序员
Scala函数定义具备如下形式 -shell
语法编程
def functionName ([list of parameters]) : [return type] = { function body return [expr] }
这里,返回类型能够是任何有效的Scala数据类型,参数列表将是由逗号分隔的变量列表,参数列表和返回类型是可选的。与Java很是类似,返回语句能够与表达式一块儿使用,以防函数返回值。 如下是将两个整数相加并返回其总和的函数,闭包
语法app
object add { def addInt( a:Int, b:Int ) : Int = { var sum:Int = 0 sum = a + b return sum } }
一个不返回任何东西的函数能够返回一个相似在Java中的void
类型,并表示该函数不返回任何内容。 在Scala中不返回任何东西的函数称为过程。编程语言
语法函数式编程
object Hello{ def printMe( ) : Unit = { println("Hello, Scala!") } }
Scala为调用方法提供了许多句法变体。如下是调用方法的标准方法 -函数
functionName( list of parameters )
若是使用对象的实例调用函数,那么可以使用与Java相似的点符号,以下所示:ui
[instance.]functionName( list of parameters )
尝试如下示例程序来定义并调用相同的函数 -
示例 -
object Demo { def main(args: Array[String]) { println( "Returned Value : " + addInt(5,7) ); } def addInt( a:Int, b:Int ) : Int = { var sum:Int = 0 sum = a + b return sum } }
将上述程序保存在源文件:Demo.scala中,使用如下命令编译和执行此程序。
Scala函数是Scala编程的核心,所以Scala被认为是函数式编程语言。如下是与Scala函数相关的几个重要概念,Scala程序员应该要理解。
object Demo { def main(args: Array[String]) { delayed(time()); } def time() = { println("Getting time in nano seconds") System.nanoTime } def delayed( t: => Long ) = { println("In delayed method") println("Param: " + t) } }
在正常的函数调用中,调用的参数按照被调用函数定义的参数顺序逐个匹配。命名参数容许您以不一样的顺序将参数传递给函数。语法只是每一个参数前面都有一个参数名称和一个等号。
尝试如下程序,它是一个简单的例子来显示具备命名参数的函数。
object Demo { 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 ); } }
将上述程序保存在源文件:Demo.scala中,使用如下命令编译和执行此程序。
Scala容许指定函数的最后一个参数可重复。 这容许客户端将可变长度参数列表传递给函数。 这里,打印字符串函数里面的args
类型,被声明为类型String *
,其实是Array [String]
。
尝试如下程序,这是一个简单的例子来演示如何使用带有可变参数的函数。
object Demo { def main(args: Array[String]) { printStrings("Hello", "Scala", "Python"); } def printStrings( args:String* ) = { var i : Int = 0; for( arg <- args ){ println("Arg value[" + i + "] = " + arg ); i = i + 1; } } }
递归在纯功能编程中起着重要做用,Scala支持递归函数。 递归表示一个函数能够重复调用自身。
尝试如下程序,它是一个很好的递归示例,它计算给定参数(数字)的阶乘。
示例
object Demo { def main(args: Array[String]) { for (i <- 1 to 10) println( "Factorial of " + i + ": = " + factorial(i) ) } def factorial(n: BigInt): BigInt = { if (n <= 1) 1 else n * factorial(n - 1) } }
Scala容许您指定函数参数的默认值。 这样一个参数能够从函数调用中选择性地省略,在这种状况下,相应的参数值将使用默认值。若是指定其中一个参数,则使用该参数将传递第一个参数,第二个参数将从默认值中获取。
尝试如下示例,它是为函数指定默认参数的示例 -
示例
object Demo { def main(args: Array[String]) { println( "Returned Value : " + addInt() ); } def addInt( a:Int = 5, b:Int = 7 ) : Int = { var sum:Int = 0 sum = a + b return sum } }
Scala容许定义高阶函数。它是将其余函数做为参数或其结果是函数的函数。
尝试如下示例程序,apply()
函数接受另外一个函数f
和值v
,并将函数f
应用于v
。
示例
object Demo { 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 Demo { 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提供了一个相对轻量级的语法来定义匿名函数。源代码中的匿名函数称为函数文字,在运行时,函数文字被实例化为称为函数值的对象。
Scala支持一级函数,函数能够用函数文字语法表达,即(x:Int)=> x + 1
,该函数能够由一个叫做函数值的对象来表示。
尝试如下表达式,它为整数建立一个后继函数 -
var inc = (x:Int) => x+1
变量inc
如今是一种能够像函数那样使用的函数 -
var x = inc(7)-1
还能够以下定义具备多个参数的函数:
var mul = (x: Int, y: Int) => x*y
变量mul
如今是能够像函数那样使用的函数 -
println(mul(3, 4))
也能够定义不带参数的函数,以下所示:
var userDir = () => { System.getProperty("user.dir") }
变量userDir
如今是能够像函数那样使用的函数 -
println( userDir )
当在调用一个函数时,把这个函数应用到参数中。 若是您传递全部预期的参数,则表示您已彻底应用它。 若是只传递几个参数并非所有参数,那么将返回部分应用的函数。这样就能够方便地绑定一些参数,其他的参数可稍后填写补上。
尝试如下,下面是一个简单的示例程序用来演示如何使用部分应用函数 -
import java.util.Date object Demo { 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) } }
将上述程序保存在源文件:Demo.scala 中,使用如下命令编译和执行此程序。
D:/> scalac Demo.scala D:/> scala Demo Mon Dec 02 12:52:41 CST 2018----message1 Mon Dec 02 12:52:41 CST 2018----message2 Mon Dec 02 12:52:41 CST 2018----message3
这里,log()
方法有两个参数:date
和message
。 咱们想要屡次调用该方法,具备相同的日期值,但不一样的消息值。能够经过将参数部分地应用到log()
方法来消除将日期传递给每一个调用的干扰。为此,首先将值绑定到date
参数,并将第二个参数绑定到其位置。 结果是存储在变量中的部分应用函数。
尝试如下示例程序以仅使用未绑定的参数消息来调用此新方法。
import java.util.Date object Demo { 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) } }
将上述程序保存在源文件:Demo.scala中,使用如下命令来编译和执行此程序。
D:\>scalac Demo.scala D:\>scala Demo Mon Dec 02 12:53:56 CST 2018----message1 Mon Dec 02 12:53:56 CST 2018----message2 Mon Dec 02 12:53:56 CST 2018----message3
柯里化(Currying)函数是一个带有多个参数,并引入到一个函数链中的函数,每一个函数都使用一个参数。 柯里化(Currying)函数用多个参数表定义,以下所示:
def strcat(s1: String)(s2: String) = s1 + s2
或者,还可使用如下语法定义柯里化(Currying)函数 -
def strcat(s1: String) = (s2: String) => s1 + s2
如下是调用柯里化(Currying)函数的语法 -
strcat("foo")("bar")
您能够根据须要在柯里化(Currying)函数上定义两个以上的参数。尝试下面一个简单的示例程序用来了解如何使用柯里化(Currying)函数 -
object Demo { 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 } }
将上述程序保存在源文件:Demo.scala 中,使用如下命令编译和执行此程序。
D:\> scalac Demo.scala D:\> scala Demo str1 + str2 = Hello, Scala!
闭包是一个函数,它返回值取决于在此函数以外声明的一个或多个变量的值。
如下代码是一个匿名函数。
val multiplier = (i:Int) => i * 10
这里,函数体i * 10
中使用的惟一变量是i
,它被定义为该函数的一个参数。尝试如下代码 -
val multiplier = (i:Int) => i * factor
乘数有两个自由变量:i
和factor
。i
是函数的一个正式参数。 所以,每当调用乘数时,它必然会有一个新的值。然而,factor
不是一个正式的参数,那这是什么呢? 再增长一行代码。
var factor = 3 val multiplier = (i:Int) => i * factor
如今factor
参考了函数以外的变量,可是在闭合的范围内。函数引用factor
,每次读取其当前值。 若是函数没有外部引用,那么它自己就会被简单地关闭,不须要外部上下文。
请尝试如下示例程序 -
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 }
将上述程序保存在源代码:Demo.scala中,使用如下命令编译和执行此程序。
D:\>scalac Demo.scala D:\>scala Demo multiplier(1) value = 3 multiplier(2) value = 6