Scala函数式编程基础讲解

发布时间:2021-07-20 11:44:06 作者:chen
来源:亿速云 阅读:163

这篇文章主要讲解了“Scala函数式编程基础讲解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Scala函数式编程基础讲解”吧!

3 函数式编程基础


在纯函数式编程语言里,变量就像数学语言里的代数符合,一经确定就不能改变。正是由于这种不可变性,使得函数和普通的值之间具有对等关系。这样函数就跟普通的值一样成为了“头等公民”,可以像任何其他数据类型一样被传递和操作。

scala不是完全的函数式编程语言,它在架构的上层提倡采用面向对象编程,而在对数据和各种底层操作作中使用函数式编程,对变量的定义既可以使用val,也可以使用var,所以它并不要求变量不可变。但在实际操作中,scala建议多用val,少用var,这样可以降低出错的概率。

函数的定义与使用

函数既然与普通的值对等,那么它也应该拥有类型的区别。

比如:

scala> val counter:(Int) => Int = {   value => value + 1}val counter: Int => Int = $Lambda$1089/230944166@1372696bscala> counter(5)val res8: Int = 6

上面定义的counter是一个函数,第2行包括了它的传入参数类型以及返回值类型定义,即 (Int) => Int

符号=>的左边是该方法的传入参数类型,右边是方法的返回值类型。

等号"=" 后面大括号中的内容就是方法体。

当函数需要定义多个参数列表时:

scala> def mult(factor:Int)(x:Int) = x*factordef mult(factor: Int)(x: Int): Intscala> mult(90)(5)val res9: Int = 450

高阶函数

当一个函数包含其它函数作为参数或作为返回值时,该函数称为高阶函数,可以说它是操作其它函数的函数。

scala> def sum(f:Int => Int, a:Int, b:Int):Int = {    if(a>b) 0 else f(a)+sum(f,a+1,b)}def sum(f: Int => Int, a: Int, b: Int): Intscala> sum(x=>x*x, 1, 5)val res10: Int = 55

上面函数的计算过程:

初始时 a = 1, b = 5

sum(x=>x*x, 1, 5)

= f(1) + sum(f, 2, 5) = 1 + f(2) +sum(f, 3, 5) = 1 + 4 + f(3) + sum(4,5)

= 1 + 4 +9 + f(4) + sum (5,5) = 1 + 4 + 9 + 16 + f(5) + sum(6,5)

= 1+ 4 + 9 + 16 + 25 + 0 = 55

闭包

有些函数的执行只依赖于传入参数的值,与调用函数的上下文无关。当函数执行时依赖于声明于函数外部的变量时,则称这个函数为闭包

偏应用函数和Curry化

  1. 偏应用函数

    一个函数在特殊应用场景下参数可能会多次取相同的值,将这个函数的部分参数整合为一个参数,传入一个新的函数中,这就称为偏应用函数。

    scala> def sum(a:Int, b:Int, c:Int):Int = {     a+b+c}def sum(a: Int, b: Int, c: Int): Intscala> sum(1,2,3)val res21: Int = 6scala> sum(1,2,4)val res22: Int = 7scala> val a = sum(1,2,_:Int)val a: Int => Int = $Lambda$1114/1028466661@5dd12d01scala> a(9)val res23: Int = 12


    定义一个新的变量a, 它将原本sum函数的第1、2个传入参数的值固定了,然后我们调用的时候只需要向 a 传入原本sum函数中的第3个参数就可以了。

  2. Curry化

    Curry化的函数是指一个函数拥有多个参数列表,并且每个参数列表中只有一个参数。

针对容器的操作

  1. 遍历

    scala标准的容器遍历方法为foreach方法。该方法的原型为:def foreach[U](f: Elem => U): Unit

    先来看一个例子:

    scala> var list = List(1,2,3)         //创建一个List容器var list: List[Int] = List(1, 2, 3)scala> var f = (i:Int) => println(i)var f: Int => Unit = $Lambda$1122/1187220855@4ad30ac5scala> list.foreach(f)123


    可以看到,foreach方法返回值类型为Unit,该函数接受一个函数f 作为参数。

    函数f 的传入参数类型为Elem,即容器中元素的类型;然后返回值类型为Unit。

    在这个例子中,我们遍历了List容器中的元素,其元素类型为Int。传入foreach函数的函数参数 f 的功能是打印元素。

    我们还可以使用中缀表示法来调用 foreach:格式为容器 foreach 应用在容器上的方法

    scala> list foreach println123


  2. 映射

    映射是指通过对容器中的元素进行某些运算来生成一个新的容器。scala中有两个典型的映射方法:map 方法和flatMap方法。

  3. 过滤

    过滤,顾名思义就是根据实际需求对容器中的元素进行筛选。scala中最经典的过滤方法是 filter,exists以及find 。

    下面举个例子来看看怎么使用filter :

    scala> val university = Map("XMU"->"Xiamen University","THU"->"Tsinghua University", "PKU"->"Peking University")val university: scala.collection.immutable.Map[String,String] = Map(XMU -> Xiamen University, THU -> Tsinghua University, PKU -> Peking University)scala> f = university filter{     kv => kv._2 contains "Xiamen"} val res39: scala.collection.immutable.Map[String,String] = Map(XMU -> Xiamen University)


    整个过程就是,首先创建一个Map容器,然后遍历整个容器,查找值含有"Xiamen"的键值对,进行过滤,得到一个新的Map容器。其中kv._2用于访问某个键值对的值,相应地,如果要访问该键值对的键,则使用kv._1

    类似的,exists 用于查找容器中是否含有某个元素,find 用于查找第一个符合条件的元素。

  4. 规约

    规约是对容器的元素进行两两运算,将其“规约”为一个值。

    先来看看最常用的reduce 方法:

    scala> val list = List(1,2,3,4,5)val list: List[Int] = List(1, 2, 3, 4, 5)scala> list.reduce(_+_)val res41: Int = 15


    reduce接收了一个二元函数f (带有2个元素) 作为参数,然后进行运算,最后结果为15,这个过程可以表示为:((((1+2)+3)+4)+5)

    所以reduce第一次接受的元素分别是1和2,然后是3和3,接着是6和4,最后是10和5,每次都将接受的两个元素相加,然后再将相加的结果作为下一次接收的两个元素中的第一个,规约操作进行到容器中的元素遍历完成为止。

  5. 拆分

    拆分操作将容器中的元素按照一定规则分割成多个子容器。常用的拆分方法有:partition、groupedBy、grouped和sliding。

感谢各位的阅读,以上就是“Scala函数式编程基础讲解”的内容了,经过本文的学习后,相信大家对Scala函数式编程基础讲解这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. Scala的函数式编程
  2. Scala基础语法介绍

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

scala

上一篇:vue移动UI框架滑动加载数据的示例分析

下一篇:怎么修改gazebo物理参数

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》