一、函数和方法
- Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。
- Scala 中使用 val 语句可以定义函数,def 语句定义方法
//定义一个方法
def sum(a:Int, b:Int) = a + b
//因为方法即操作符,所以在调用方法时有时可以省略括号,而函数必须带上括号
//例如加号+就是一个方法,a + b也可以写成a.+(b)
定义一个函数
val sum2 = (a: Int, b: Int) => a + b
- 方法不能作为参数进行传递调用!!!,函数因为是对象所以可以作为参数进行传递!!!
- 3,但是Scala中可以把方法转换成函数
//后面加下划线可以把方法转换成函数,注意要有空格
sum _
- 注:直接传方法也可以运行,Scala会自动将其转换成函数
def sum(a: Int, b: Int): Int = a.+(b)
val sum2 = (a: Int, b: Int) => a + b
def fn(f: (Int, Int) => Int) = {
println(f(3, 10))
}
def main(args: Array[String]): Unit = {
fn(sum)//输出13,Scala会自动将sum方法转换成函数
fn(sum2)//输出13
}
二、scala中的匿名函数
Scala提供了一个相对轻量级的语法来定义匿名函数。源代码中的匿名函数称为函数文字,在运行时,函数文字被实例化为称为函数值的对象。
val fun2 = (content:String) =>println(content)
var userDir = () => { System.getProperty("user.dir") }
三、高阶函数
1、scala的高阶函数:把函数当做参数传入到另一个函数中,函数的参数是函数
scala> val sayHello = (name: String) => println("my name is:" + name)
sayHello: String => Unit = <function1>
scala> sayHello("cyony")
my name is:cyony
scala> def introduce(fun: (String) => Unit, name: String, age: Int): Unit = {
| println("my age is:"+age)
| fun(name)
| }
introduce: (fun: String => Unit, name: String, age: Int)Unit
scala> introduce(sayHello,"cyony",25)
my age is:25
my name is:cyony
上面一步定义了匿名函数,且赋值给了sayHello变量。然后定义了一个introduce函数,他的签名为,第一参数为一个方法,此fun的签名为一个String变量,返回类型是Unit;第二个参数是一个String类型的变量;第三个参数是Int类型的变量。因为fun变量自己就是一个函数,且又传给了introduce函数,所以称fun为他的高阶函数。在调用的时候,为fun传入sayHello变量,最终打印结果如上所示。
2、函数的返回值就是一个函数:函数的返回值是函数 == 有返回高阶函数
scala> def introduce(age: Int) = (name: String) => println("my name is:" + name + ",my age is:" + age)
introduce: (age: Int)String => Unit
scala> val introduceFun = introduce(25)
introduceFun: String => Unit = <function1>
scala> introduceFun("cyony")
my name is:cyony,my age is:25
这个例子和上面的相比,有点不同,introduce函数本身返回的也是一个函数,可以看到repl的提示,返回一个签名为String,返回为Unit的匿名函数,函数主体则是打印那句话。在调用的时候,首先得到这个匿名函数,然后再调用这个匿名函数。这个匿名函数同样是introduce的高阶函数。
四、科里化
example
是指一个函数有两个参数,可以将一个函数转换成两个函数:第一个函数是第一个参数。第二个函数是接收第二个参数
def sum(x:Int, y:Int) = x +y
等价于
def sum_Currying(x:Int) = (y:Int) =>x+y 等价于def sum_Currying(x:Int) (y:Int) =x+y
sum_Currying(1)(2)
Currying函数
scala> def introduce(age: Int)(name: String) = println("my name is:" + name + ",my age is:" + age)
introduce: (age: Int)(name: String)Unit
scala> introduce(25)("cyony")
my name is:cyony,my age is:25
函数的currying化行为本质上也是一个高阶函数:接受现有的函数,返回新函数。 这个例子就是对上一个例子的currying化操作。传入第一个参数后返回一个函数,然后再传入第二个参数,完成第二个函数。这样就讲一个高阶函数拆解成两个一阶函数。
高阶函数类型推断
scala> def triple(fun: (Int) => Int, num: Int) = {
| fun(num)
| }
triple: (fun: Int => Int, num: Int)Int
scala> triple(_*3,5)
res12: Int = 15
如上所示,定义了一个triple函数,他的签名是一个高阶函数和一个整形。在这个函数实际使用的时候,用了占位符来替换传入参数,因为传入的参数肯定是Int类型,且在此主体中只使用了一次,所以可以直接用占位符表示,省去了函数签名以及返回,直接定义主体,使得语法非常精简。
五、函数闭包
闭包的方式:函数超出了自己的作用域的时候,内部的变量依然可以访问外部。
1,闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
2,一旦函数引用了外部的变量或常量,那么就称此函数为闭包函数。
val x = 3
val fn = (y: Int) => x + y//闭包
(x:Int) => println(x+10) //不是闭包。
网友评论