16_Scala_函数式编程高级_偏函数_高级函数_闭包柯里化_递归
【摘要】 偏函数PartialFunction (大括号内的一组case语句封装为函数)
匿名函数
高级函数
类型推断
闭包
柯里化
递归
偏函数PartialFunction (大括号内的一组case语句封装为函数)
1 对符合某个条件的情况下,进行逻辑操作时 它只对会作用于指定类型的参数或指定范围值的参数实施计算,超出范围的值会忽略
2 将包在大括号内的一组case语句封装为函数
3 偏函数继承一个特质 PartialFunction
偏函数简化形式
函数作为一个变量传入到了另一个函数中,那么该作为参数的函数的类型是:function1,即:(参数类型) => 返回类型
object PartialFunTest02 {
def main(args: Array[String]): Unit = {
val list1 = List(1, 2, 3, 4, "hello")
//使用偏函数
//说明:如果是使用偏函数,则不能使用map,应该使用collect
//说明一下偏函数的执行流程
//1. 遍历list所有元素
//2. 然后调用 val element = if(partialFun-isDefinedAt(list单个元素)) {partialFun-apply(list单个元素) }
//3. 每得到一个 element,放入到新的集合,最后返回
val list2 = list1.collect(pFun)
println(list2 ) //List(2, 3, 4, 5)
val list3 = list1.collect(pFun2)
println(list3 ) //List(2, 3, 4, 5)
// 方式三 直接接 list.collect { case 1 case 2 }
val list4 = list1.collect {
case i: Int => i + 1
case j: Double => (j * 2).toInt
}
println( list3 )
}
// 方式1 正常定义方法 override 重写 def isDefinedAt 重写 def apply
//1. PartialFunction[Any,Int] 表示偏函数接收的参数类型是Any,返回类型是Int
//2. isDefinedAt(x: Any) 如果返回true ,就会去调用 apply 构建对象实例,如果是false,过滤
//3. apply 构造器 ,对传入的值 + 1,并返回(新的集合)
val pFun= new PartialFunction[Any, Int] {
override def isDefinedAt(x: Any): Boolean = x.isInstanceOf[Int]
override def apply(v1: Any): Int = v1.asInstanceOf[Int] + 1
}
// 方式2 简写 定义方法
def pFun2: PartialFunction[Any, Int] ={
// case i: int ( def isDefinedAt(x: Any): Boolean = x.isInstanceOf[Int])
// => i + 1 (def apply(v1: Any): Int = v1.asInstanceOf[Int] + 1 )
case i : Int => i +1
case j: Double => (j * 2).toInt
}
}
匿名函数
函数作为一个变量传入到了另一个函数中,
那么该作为参数的函数的类型是:function1,即:(参数类型) => 返回类型
object AnonyFunParameter {
def main(args: Array[String]): Unit = {
// 函数作为参数 传入
//def map[B, That](f: A => B) 的声明中的 f: A => B 一个函数
//map(plus(_)) 中的plus(_) 就是将plus这个函数当做一个参数传给了map,_这里代表从集合中遍历出来的一个元素。
//plus(_) 这里也可以写成 plus 表示对 Array(1,2,3,4) 遍历,将每次遍历的元素传给plus的 x
//进行 x * 2 运算后,返回新的Int ,并加入到新的集合 result1 中
val result1 = Array(1, 2, 3, 4).map(plus(_))
println(result1.mkString("_")) //2_4_6_8
//1. 在scala中,函数也是有类型,比如plus就是 <function1>
// println("puls的函数类型function1" + (plus _))
// 匿名函数
//1. 不需要写 def 函数名
//2. 不需要写返回类型,使用类型推导
//3. = 变成 =>
//4. 如果有多行,则使用{} 包括
var triple = (x: Int) => x * 3
println(triple(3)) //9
val arry2 = Array(1, 2, 3).map((x: Int) => x * 4)
println(arry2.mkString(",")) //4,8,12
}
// 函数作为参数 传入
def plus(x: Int) = x *2
}
高阶函数
能够接收函数作为参数的函数,也可以返回一个函数,叫做高阶函数 (higher-order function)
object HighorderTest2 {
def main(args: Array[String]): Unit = {
val ho1 =horder2 (sum, mod, 5.0)
// println(ho1 )
// result1 就是 (y: Int) => 100 - y
val result1 = minusxy(100)
println( "result1类型:" + result1)
println(result1(50 )) //100 -50
//也可以一步到位的调用 柯里化
val result2 = minusxy(10)(5)
// println(result2)
}
// 接收一个函数
def sum(d: Double): Double = {
d + d}
def mod(d:Double): Int = {
d.toInt % 2}
//高阶函数 能够接受函数作为参数,返回一个函数 的函数,叫做高阶函数 (higher-order function)
// horder2 接受 f1, f2 函数
def horder2( f1: Double => Double, f2: Double => Int, n1: Double) ={
f1(f2(n1))
}
// 返回一个函数
//1. minusxy是高阶函数,因为它返回匿名函数
//2. 返回的匿名函数 (y: Int) => x - y
//3. 返回的匿名函数可以使用变量接收
def minusxy(x: Int) = {
(y: Int) => x - y //返回一个 匿名函数;闭包 x 是从外部传进来的,(y: Int) => x - y; x与这个匿名函数形成一个整体
}
}
类型推断
当遍历list时,参数类型是可以推断出来的,可省略数据类型
当传入的函数,只有单个参数时,可以省去括号
如果变量只在=>右边只出现一次,可以用_来代替 同时=>左边都省略
object ParameterInferTest {
def main(args: Array[String]): Unit = {
// 类型推断 & 简化
// 当遍历list时,参数类型是可以推断出来的,可省略数据类型
// 当传入的函数,只有单个参数时,可以省去括号
// 如果变量只在=>右边只出现一次,可以用_来代替 同时=>左边都省略
val list = List(1, 2, 3, 4)
println(list.map((x:Int)=>x + 1))
println(list.map((x)=>x + 1)) //list 里面元素都是int x 肯定也是 int,省略类型
println(list.map(x=>x + 1)) // 一个参数是 () 省略
println(list.map( _ + 1)) // 右边只出现一次,可以用_来代替, => 省略
}
}
闭包 closure 一个函数和与其相关的引用环境组合的一个整体(类似对象方法和属性关系)
def minusxy(x: Int) = (y: Int) => x - y
object ClosureTest {
def main(args: Array[String]): Unit = {
val func_closure = makeend(".mp4")
println(func_closure("alex")) //alex.mp4
println(func_closure("bob.mp4")) //bob.mp4
// 柯里化
val str = makeend(".mp3")("sumi")
println(str)
}
// 闭包 一个函数和与其相关的引用环境组合的一个整体(类似对象方法和属性关系)
// 下面 一个匿名函数 (filename) =>{ } 引用一个参数 (endpoint) 形成一个整体
def makeend( endpoint: String) = {
(filename: String ) => {
if (filename.endsWith(endpoint))
{ filename}
else
{filename + endpoint}
}}
}
}
函数柯里化(curry)
函数编程中,接受多个参数的函数都可以转化为接受单个参数的函数,这个转化过程就叫柯里化 ,证明函数只需要一个参数而已。
object CurryTest1 {
def main(args: Array[String]): Unit = {
println(mul1(2, 5))
println(mul2(2)(5))
println(mul3(2)(5))
// 柯里化例2
// str1.checkeq("sumi")((s1: String, s2: String) => s1.equals(s2))
// str1.checkeq("sumi")((s1, s2) => s1.equals(s2))
// str1.checkeq("sumi")( _.equals(_))
val str1 = "hello"
println(str1.checkeq("alex")(eq _)) //false
println(str1.checkeq("bob")(_ equals (_))) //false
println(str1.checkeq("HELLO")(_ equals (_))) //true
}
// 常规比较, s1, s2 传入, 返回Boolean
def eq(s1: String, s2: String) : Boolean ={s1.equals(s2)}
// 隐式类 如果 一个s 是字符串 传入,就可以 使用 checkeq方法
implicit class TestEQ (s: String ){
def checkeq (ss: String)(f: (String, String)=> Boolean): Boolean ={
f(s.toLowerCase, ss.toLowerCase)
}
}
//柯里化 函数编程中,接受多个参数的函数都可以转化为接受单个参数的函数
// 柯里化 1 常规方式
def mul1 (x:Int, y:Int) = x * y
// 柯里化 2 闭包方式
def mul2 (x:Int) = (y: Int) => x * y
// 柯里化 3 柯里化
def mul3(x:Int)(y:Int) = x * y
}
控制抽象是这样的函数,满足如下条件
参数是函数
函数参数没有输入值也没有返回值
object AbstractControlTest1 {
def main(args: Array[String]): Unit = {
//控制抽象是这样的函数,满足如下条件
//参数是函数
//函数参数没有输入值也没有返回值
//说明
//1 函数名为 mywhile也是个控制抽象 , 实现了类似while循环的效果
//2. condition: => Boolean 是 没有输入值,返回Boolean类型函数
//3. block: => Unit 没有输入值,也没有返回值的函数 ,调用时候传入代码块(就是匿名函数)
def mywhile(condition: => Boolean)(block: => Unit): Unit ={
if(!condition) {
block // x= 9 ,x = 8 x =7 ....
mywhile(condition)(block)
}}
var x =5
// mywhile()()
mywhile(x==0)({x -=1; println(x)})
// 简化
mywhile(x==0){x -=1; println(x)}
}
}
递归
object recursiveTest {
def main(args: Array[String]): Unit = {
val now: Date = new Date()
val dateFormat: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val date = dateFormat.format(now)
println("date=" + date) //输出时间
var num = BigInt(1)
var sum = BigInt(0)
var res = mx(num,sum)
println("res=" + res)
val now2: Date = new Date()
val date2 = dateFormat.format(now2)
println("date2=" + date2) //输出时间
}
def mx(num: BigInt, sum: BigInt): BigInt = {
if (num <= 99999999l) return mx(num + 1, sum + num)
else return sum
}
//求最大值
def max(xs: List[Int]): Int = {
if (xs.isEmpty)
throw new java.util.NoSuchElementException
if (xs.size == 1)
xs.head
else if (xs.head > max(xs.tail)) xs.head else max(xs.tail)
}
// 翻转
def reverse(xs: String): String =
if (xs.length == 1) xs else reverse(xs.tail) + xs.head
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)