函数式编程-函数对象作为方法的参数
scala
复制代码
package com.zishi.scala.a02.okk05
/**
* 将函数对象作为方法的参数来使用,
* 函数本身就是对象,
* 对象的使用领域:变量,方法参数,返回值类型
*
* 类比Java
* public void test(User user) {
* }
*
* User user = new User();
*
* test(user); 对象作为方法的参数
* test(new User());
*/
object Test05_Lambda01 {
def main(args: Array[String]): Unit = {
// 创建方法对象
def fun33(age: Int): String = {
"Hello:" + age
}
/**
* 等同于
* def test(f: Function1[Int, String]) : Unit = {}
*/
def test(f: (Int) => String): Unit = {
println(f(23))
}
val f2 = fun33 _
test(f2) // Hello:23
def sum(x:Int, y:Int): Int = {
x + y
}
def sub(x: Int, y: Int): Int = {
x - y
}
def test2(fun: (Int, Int) => Int): Unit = {
val i = fun(10, 20)
println(i)
}
// 将函数名称作为参数传递为一个函数作为参数,此时不需要下划线
test2(sum)
//TODO: 这里函数的名称sub真的很重要吗?
// 类比Java:test(new User())
test2(sub)
// TODO: 将参数传递的名字取消掉
// 如果函数声明没有def和名称,那么就是匿名函数
test2((x: Int, y: Int) => {
x * y
})
// 将匿名函数赋值给一个变量
val a = (x: Int, y: Int) => {
x / y
}
test2(a)
// 匿名函数的简化原则
//(1)参数的类型可以省略,会根据形参进行自动的推导
test2((x, y) => {
x * y
})
//(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。
//(3)匿名函数如果只有一行,则大括号也可以省略
test2((x, y) => x * y)
//(4)如果参数只出现一次,并且按照顺序执行一次,则参数省略且后面参数可以用_代替
println("-------------------")
test2(_ * _) // 下划线类似占位符,第一个下划线代表第一个参数,依次类推
//(5) 如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线
// 定义一个函数,以函数作为参数输入
def f(func: String => Unit): Unit = {
func("abcde")
}
f((name: String) => {
println(name)
})
println("========================")
// 匿名函数的简化原则
//(1)参数的类型可以省略,会根据形参进行自动的推导
f((name) => {
println(name)
})
//(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。
f(name => {
println(name)
})
//(3)匿名函数如果只有一行,则大括号也可以省略
f(name => println(name))
//(4) 如果参数只出现一次,则参数省略且后面参数可以用_代替
f(println(_))
//(5) 如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线
f(println _)
f(println)
}
}
练习
scala
复制代码
package com.zishi.scala.a02.okk05
object Test05_Lambda02 {
def main(args: Array[String]): Unit = {
// 实际示例,定义一个"二元运算"函数,只操作1和2两个数,但是具体运算通过参数传入
def dualFunctionOneAndTwo(fun: (Int, Int) => Int): Int = {
fun(1, 2)
}
val add = (a: Int, b: Int) => a + b
val minus = (a: Int, b: Int) => a - b
println(dualFunctionOneAndTwo(add))
println(dualFunctionOneAndTwo(minus))
// 匿名函数简化
println(dualFunctionOneAndTwo((a: Int, b: Int) => a + b))
println(dualFunctionOneAndTwo((a: Int, b: Int) => a - b))
println(dualFunctionOneAndTwo((a, b) => a + b))
println(dualFunctionOneAndTwo(_ + _))
println(dualFunctionOneAndTwo(_ - _))
println(dualFunctionOneAndTwo((a, b) => b - a))
println(dualFunctionOneAndTwo(-_ + _))
// Java里面存在引用类型和基本类型同时作为方法的参数 void test(int x, User u);
// 类比java
def cal(x: Int, func: (Int, Int) => Int, y: Int) = {
func(x, y)
}
def sum(x: Int, y: Int) = {
x + y
}
println("....")
println(cal(3,
(x: Int, y: Int) => {
x + y
}, 5))
println(cal(3, (x: Int, y: Int) => x + y, 5))
println(cal(3, (x, y) => x + y, 5))
println(cal(3, _ + _, 5))
}
}
函数作为返回值
scala
复制代码
package com.zishi.scala.a02.okk05
/**
* 函数作为返回值返回
* 类比Java
* public User test() {
* User user = new User();
* return user;
* }
*
* public User test() {
* return new User();
* }
*/
object Test05_Lambda03 {
def main(args: Array[String]): Unit = {
// 函数作为返回值返回
def outer() = {
def inner(): Unit = {
print("abc")
}
inner _
}
val f1 = outer()
f1()
//下面的调用更诡异
outer()() // abc
println("...............")
def outer2() = {
//def inner(name: String): Unit = print(s"abc${name}")
def inner(name: String): Unit = print(s"abc${name}")
inner _
}
val f2 = outer2()
f2("aege") // abcabcaege
def outer3(x: Int) = {
def mid(f : (Int, Int) => Int) = {
def inner(y: Int) = {
f(x, y)
}
inner _
}
mid _
}
println()
val mid = outer3(1)
val inner = mid( _ + _)
val res = inner(3)
println(res)
val res2 = outer3(1)( _ + _)(3)
println(res2)
}
}
高阶函数01
scala
复制代码
package com.zishi.scala.a02.okk05
object Test06_HighOrderFunction01 {
def main(args: Array[String]): Unit = {
def f(n: Int): Int = {
println("f调用")
n + 1
}
val result: Int = f(123)
println(result) // 124
// 1. 函数作为值进行传递
val f1: Int => Int = f
val f2 = f _
println(f1) // com.zishi.scala.okk05.Test06_HighOrderFunction$$$Lambda$16/0x00000008000d7040@1e67a849
println(f1(12)) // 13
println(f2) // com.zishi.scala.okk05.Test06_HighOrderFunction$$$Lambda$17/0x00000008000d6840@57d5872c
println(f2(35)) // 36
def fun(): Int = {
println("fun调用")
1
}
val f3: () => Int = fun
val f4 = fun _
println(f3) // com.zishi.scala.okk05.Test06_HighOrderFunction$$$Lambda$18/0x00000008000d6040@64c87930
println(f4) // com.zishi.scala.okk05.Test06_HighOrderFunction$$$Lambda$19/0x00000008000d6440@400cff1a
}
}
高阶函数02
scala
复制代码
object Test06_HighOrderFunction02 {
def main(args: Array[String]): Unit = {
// 2. 函数作为参数进行传递
// 定义二元计算函数
def dualEval(op: (Int, Int) => Int, a: Int, b: Int): Int = {
op(a, b)
}
def add(a: Int, b: Int): Int = {
a + b
}
println(dualEval(add, 12, 35))
println(dualEval((a, b) => a + b, 12, 35))
println(dualEval(_ + _, 12, 35))
// 3. 函数作为函数的返回值返回
def f5(): Int => Unit = {
def f6(a: Int): Unit = {
println("f6调用 " + a)
}
f6 // 将函数直接返回
}
// val f6 = f5()
// println(f6)
// println(f6(25))
println(f5()(25))
}
}
object Test06_HighOrderFunction03 {
def main(args: Array[String]): Unit = {
// 3. 函数作为函数的返回值返回
def f5(): Int => Unit = {
def f6(a: Int): Unit = {
println("f6调用 " + a)
}
f6 // 将函数直接返回
}
// val f6 = f5()
// println(f6)
// println(f6(25))
println(f5()(25))
}
}
练习
scala
复制代码
package com.zishi.scala.a02.okk05
/**
* 函数作为返回值
*/
object Test08_Practice {
def main(args: Array[String]): Unit = {
// 2. 练习2
def func(i: Int): String => (Char => Boolean) = {
def f1(s: String): Char => Boolean = {
def f2(c: Char): Boolean = {
if (i == 0 && s == "" && c == '0') false else true
}
f2
}
f1
}
println(func(0)("")('0'))//false
println(func(0)("")('1'))//true
println(func(23)("")('0'))//true
println(func(0)("hello")('0'))//true
// 匿名函数简写
def func1(i: Int): String => (Char => Boolean) = {
s => c => if (i == 0 && s == "" && c == '0') false else true
}
println(func1(0)("")('0'))//false
println(func1(0)("")('1'))//true
println(func1(23)("")('0'))//true
println(func1(0)("hello")('0'))//true
// 柯里化
def func2(i: Int)(s: String)(c: Char): Boolean = {
if (i == 0 && s == "" && c == '0') false else true
}
println(func2(0)("")('0'))//false
println(func2(0)("")('1'))//true
println(func2(23)("")('0'))//true
println(func2(0)("hello")('0'))//true
}
}
object Test08_Practice01 {
def main(args: Array[String]): Unit = {
// 1. 练习1
val fun = (i: Int, s: String, c: Char) => {
if (i == 0 && s == "" && c == '0') false else true
}
println(fun(0, "", '0'))//false
println(fun(0, "", '1'))//true
println(fun(23, "", '0'))//true
println(fun(0, "hello", '0'))//true
}
}
scala
复制代码
package com.zishi.scala.a02.okk05
/**
* 函数作为返回值
*/
object Test08_Practice {
def main(args: Array[String]): Unit = {
// 2. 练习2 内层函数可以使用外层函数的参数
// func 参数列表:i: Int, 返回值类型(函数类型):String => (Char => Boolean)
def func(i: Int): String => (Char => Boolean) = {
// f1函数: 参数列表:s: String, 返回值类型:Char => Boolean
def f1(s: String): Char => Boolean = {
// f2函数: 参数列表:c: Char, 返回值类型:Boolean
def f2(c: Char): Boolean = {
if (i == 0 && s == "" && c == '0') false else true
}
f2
}
f1
}
println(func(0)("")('0'))//false
println(func(0)("")('1'))//true
println(func(23)("")('0'))//true
println(func(0)("hello")('0'))//true
def func33(i: Int): String => (Char => Boolean) = {
// f1函数: 参数列表:s: String, 返回值类型:Char => Boolean
def f1(s: String): Char => Boolean = {
// f2函数: 参数列表:c: Char, 返回值类型:Boolean
// def f2(c: Char): Boolean = if (i == 0 && s == "" && c == '0') false else true
//def f2(c: Char) = if (i == 0 && s == "" && c == '0') false else true
// val f2 = (c: Char) => if (i == 0 && s == "" && c == '0') false else true
// c => if (i == 0 && s == "" && c == '0') false else true
c => true
}
f1
}
def func44(i: Int): String => (Char => Boolean) = {
// f1函数: 参数列表:s: String, 返回值类型:Char => Boolean
//def f1(s: String): Char => Boolean = c => if (i == 0 && s == "" && c == '0') false else true
//def f1(s: String) = (c:Char) => if (i == 0 && s == "" && c == '0') false else true
//val f1 = (s: String) => (c:Char) => if (i == 0 && s == "" && c == '0') false else true
//(s: String) => (c:Char) => if (i == 0 && s == "" && c == '0') false else true
s => c => if (i == 0 && s == "" && c == '0') false else true
}
// 匿名函数简写
def func1(i: Int): String => (Char => Boolean) = {
s => c => if (i == 0 && s == "" && c == '0') false else true
}
println(func1(0)("")('0'))//false
println(func1(0)("")('1'))//true
println(func1(23)("")('0'))//true
println(func1(0)("hello")('0'))//true
// 柯里化
def func2(i: Int)(s: String)(c: Char): Boolean = {
if (i == 0 && s == "" && c == '0') false else true
}
println(func2(0)("")('0'))//false
println(func2(0)("")('1'))//true
println(func2(23)("")('0'))//true
println(func2(0)("hello")('0'))//true
}
}
scala
复制代码
package com.zishi.scala.a02.okk05
/**
* 函数至简原则注意事项
*/
object Test08_Practice02 {
def main(args: Array[String]): Unit = {
def test(name: String, f: String => Unit): Unit = {
f(name)
}
def func(name: String): Unit = {
println("name:" + name)
}
// 1. 调用
test("zbc", func)
// 2. 化简
test("zbc", (name: String) => println("name:" + name))
//3, 化简
test("zbc", name => println("name:" + name))
//4, 下面的化简不对
// _ 代表第二个参数,第二个参数是函数对象,并不是函数对象的参数
test("zbc", _ => println("name:" + _)) //输出结果为:com.zishi.scala.a02.okk05.Test08_Practice02$$$Lambda$18/0x000000080009d840@2ea6137
// 报错:type mismatch, 返回的是Unit
// 这是因为这里使用的函数的嵌套。不确定下划线 _ 是哪层函数的简化
// test("zbc",println("name:" + _))
// 做个如下变形
def test2(f: String => Unit): Unit = {
f("测试变形")
}
def func2(name: String): Unit = {
println("func2:" + name)
}
// 1. 化简
test2((name: String) => println("func2:" + name))
// 2. 化简
test2(name => println("func2:" + name))
//3. 简化
test2(name => println(name))
test2(println(_))
test2(println _)
test2(println)
}
}