Scala函数

来源:互联网 发布:骆驼 薛之谦 知乎 编辑:程序博客网 时间:2024/06/05 10:56

Scala是一门函数式语言,函数在Scala里属于First-Class Value,意味着在Scala中函数可以像其它值一样用作参数或者返回值,也可以赋值给变量或存储在某些存储结构中。Scala对于函数有很多特性能能够使代码更加简洁,复用性更高。

函数定义

def functionName(paramName : paramType) : returnType = {
        //TODO  function body
}
scala> def sum(a : Int, b : Int) : Int = {     | a + b     | }sum: (a: Int, b: Int)Intscala> sum(1,2)res0: Int = 3
在REPL中定义了一个函数sum,函数接收两个参数a和b,类型均为Int,返回类型也为Int,函数返回两个参数的和。如果函数体只有一个语句大括号是可以省略的。另外基于Scala强大的类型推导机制,函数的返回类型往往也可以省略。

scala> def sum(a : Int, b : Int) = a + bsum: (a: Int, b: Int)Intscala> sum(1,2)res1: Int = 3

高阶函数

在Scala中,高阶函数表示使用其它函数作为参数或者作为返回值的函数。在介绍高阶函数之前先介绍“函数类型”和“匿名函数”两个概念。
函数类型 : A => B表示该函数接收类型为A的参数并返回类型为B的返回结果。A可以是参数类型列表。如下highOrderFunc的参数为一个函数f,函数f的类型为(Int, Int) => Int
scala> def sum(a : Int, b : Int) = a + bsum: (a: Int, b: Int)Intscala> def highOrderFunc(f : (Int, Int) => Int) : Int = f(1,2)highOrderFunc: (f: (Int, Int) => Int)Intscala> highOrderFunc(sum)res4: Int = 3

匿名函数:匿名函数的定义为:(参数列表) => {函数体}。在REPL中定义了一个匿名函数,自动生成的变量名为res2,可以通过res2来调用刚刚定义的匿名函数。

scala> (a : Int, b : Int) => a + b
res2: (Int, Int) => Int = <function2>

scala> res2(1, 2)
res3: Int = 3

scala> def highOrderFunc2() = (x: Int, y: Int) => x * x + y * y
highOrderFunc2: ()(Int, Int) => Int

scala> val func2 = highOrderFunc2()
func2: (Int, Int) => Int = <function2>

scala> func2(2,3)
res2: Int = 13

函数参数求值方式

在Scala语言中,函数实参的求值方式有call by value和call by name两种方式,参数定义方式分别为
  • Call By Value: x: Int
  • Call By Name: x: => Int
scala> def func1(x: Int, y: Int) = x + yfunc1: (x: Int, y: Int)Intscala> def fund2(x: Int, y: => Int) = x + yfund2: (x: Int, y: => Int)Int

func1有两个Int类型的参数,其求职策略均为Call By Value。func2也有两个参数其中参数x的求值策略为Call By Value,y的求值策略为Call By Name。
  • Call By Value: 对函数实参的求值只做一次,在函数中的多次使用值均相同
  • Call By Name:参数在函数中每次使用均会求值
scala> var count = 0count: Int = 0scala> def addOne: Int = {     | count += 1     | count     | }addOne: Intscala> def func1(x: Int) = {     | println("count=" + x)     | println("count=" + x)     | }func1: (x: Int)Unitscala> def func2(x: => Int) = {     | println("count=" + x)     | println("count=" + x)     | }func2: (x: => Int)Unitscala> func1(addOne)count=1count=1scala> func2(addOne)count=2count=3

在REPL中先定义了一个变量count值为0,定义了一个addOne函数,在函数中对count加1并返回count的当前值。函数func1和func2均两次打印传入的参数x。func1的求值方式为Call By Value,func2的求值方式为Call By Name。第一次调用func1(addOne),会首先调用addOne对count加1并返回1,此时x的值就为1,两次打印的结果也为1.调用func2并不会首先执行addOne求出x的值,而是用addOne替换x,两次打印实际上变为println(“count=“ + addOne)  println(“count=“ + addOne)。因此addOne会被执行两次。最终打印出的结果为2和3.这就是call by value和call by name的区别。

原创粉丝点击