2021年大数据常用语言Scala(三十七):scala高级用法 高阶函数用法

举报
Lansonli 发表于 2021/09/28 23:45:23 2021/09/28
【摘要】 目录 高阶函数用法 作为值的函数 匿名函数 柯里化(多参数列表) 闭包 高阶函数用法 Scala 混合了面向对象和函数式的特性,在函数式编程语言中,函数是“头等公民”,它和Int、String、Class等其他类型处于同等的地位,可以像其他任何数据类型一样被传递和操作。 高阶函数包含:作为值的函数、匿名函数、闭包、柯里...

目录

高阶函数用法

作为值的函数

匿名函数

柯里化(多参数列表)

闭包


高阶函数用法

Scala 混合了面向对象和函数式的特性,在函数式编程语言中,函数是“头等公民”,它和Int、String、Class等其他类型处于同等的地位,可以像其他任何数据类型一样被传递和操作。

高阶函数包含:作为值的函数、匿名函数、闭包、柯里化等等。

 

作为值的函数

在scala中,函数就像和数字、字符串一样,可以将函数传递给一个方法。我们可以对算法进行封装,然后将具体的动作传递给算法,这种特性很有用。

我们之前学习过List的map方法,它就可以接收一个函数,完成List的转换。

示例:将一个小数列表中的每个元素转换为对应个数的小星星

List(1, 2, 3...) => *, \, \ 

代码:


  
  1. val listList(1234)
  2. // 字符串*方法,表示生成指定数量的字符串
  3. val func_num2star = (num:Int) => "*" * num
  4. print(list.map(func_num2star))

 

匿名函数

上面的代码,给(num:Int) => "*" * num函数赋值给了一个变量,但是这种写法有一些啰嗦。在scala中,可以不需要给函数赋值给变量,没有赋值给变量的函数就是匿名函数

示例:优化上述代码


  
  1. val listList(1234)
  2. list.map(num => "*" * num).foreach(println)
  3. // 因为此处num变量只使用了一次,而且只是进行简单的计算,所以可以省略参数列表,使用_替代参数
  4. list.map("*" * _).foreach(println)

 

柯里化(多参数列表)

list.fold(100)(_ + _)

柯里化(Currying)允许方法接收多个参数列表的语法特性。

多数用于隐式转换或者在逻辑上划分不同批次的参数用。

特点:参数如果不传递完全,得到一个函数

 

柯里化过程解析

使用柯里化,让传递匿名函数作为参数的语法更为简洁

示例:编写一个泛型方法,用来完成两个值类型的计算(具体的计算封装到函数中)


  
  1. object CurryingDemo2 {
  2.   // 实现对两个数进行计算的方法
  3.   def calc[A <: AnyVal](x:A, y:A, func_calc:(A, A)=>A) = {
  4.     func_calc(x, y)
  5.   }
  6.   // 柯里化:实现对两个数进行计算
  7.   def calc_carried[A <: AnyVal](x:A, y:A)(func_calc:(A, A)=>A) = {
  8.     func_calc(x, y)
  9.   }
  10.   def main(args: Array[String]): Unit = {
  11.     // 这种写法是不能被简化的,必须要写出函数的定义
  12.     println(calc(10, 10, (x:Int, y:Int)=> x + y))
  13.     println(calc(10.1, 10.2, (x:Double, y:Double)=> x*y))
  14.     
  15.     // 柯里化之后可以快乐地使用下划线了
  16.     println(calc_carried(10, 10)(_ + _))
  17.     println(calc_carried(10.1, 10.2)(_ * _))
  18.     println(calc_carried(100.2, 10)(_ - _))
  19.   }
  20. }

 

闭包

闭包其实就是一个函数,只不过这个函数的返回值依赖于声明在函数外部的变量。

可以简单认为,就是可以访问不在当前作用域范围的一个函数。

可以不修改方法体,通过外部变量来控制方法返回结果

示例:定义一个闭包


  
  1. object ClosureDemo {
  2.   def add(x:Int) = {
  3.     val y = 10
  4.     // add返回一个函数,该函数引用了add方法的一个局部变量
  5.     val funcAdd = () => x + y
  6.     funcAdd
  7.   }
  8.   def main(args: Array[String]): Unit = {
  9.     // 调用add方法时,任然可以引用到y的值
  10.     // funcAdd函数就是一个闭包
  11.     println(add(10)())
  12.   }
  13. }

 

上面的演示只是使用一个普通的int值来做的闭包。 如果依赖的外部变量是一个函数呢?

 

那就是,无需修改方法体, 修改外部函数就能修改计算逻辑。

文章来源: lansonli.blog.csdn.net,作者:Lansonli,版权归原作者所有,如需转载,请联系作者。

原文链接:lansonli.blog.csdn.net/article/details/116810276

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。