• Scala函数式编程



    原创申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址
    全文共计3851字,阅读大概需要3分钟
    欢迎关注我的个人公众号:不懂开发的程序猿

    1. 实验室名称:

    大数据实验教学系统

    2. 实验项目名称:

    Scala函数式编程

    3. 实验学时:

    4. 实验原理:

    1、Scala函数
      当程序越来越大,你需要将代码细化为小的容易管理的模块。Scala 支持多种方法来细化程序代码,这些方法也为有经验的程序员已经掌握的:使用函数。
      Scala中函数可以不依赖于类、对象、接口单独存在,函数可以作为函数的参数、返回值。
    2、Scala高阶函数
      高阶函数是函数式编程里面一个非常重要的特色,所谓的高阶函数,即某个函数的参数或返回值也是函数,这样的函数被称为”高阶函数”。

    5. 实验目的:

    掌握Scala函数式编程
      掌握Scala常用高阶函数

    6. 实验内容:

    1、学习使用Scala函数式编程
      2、学习Scala高阶函数的应用。

    7. 实验器材(设备、虚拟机名称):

    硬件:x86_64 ubuntu 16.04服务器
      软件:JDK 1.8.162,Scala-2.11.11

    8. 实验步骤:

    8.1 Scala函数式编程

    1、函数字面量。
      函数字面量指的是在源代码中的一个未命名函数或匿名函数。在程序中可以像使用一个字符串变量一样使用它。它还可以作为一个输入参数传递给一个高阶方法或高阶函数。另外,它也可以被赋给一个变量。
      请启动shell,在paste模式下,键入以下代码:

    1.	//定义函数
    2.	(x:Int) => {println("hello");println(x + x)}
    3.	     
    4.	//一切皆对象,当然函数也是对象,所以可以将它赋给一个变量
    5.	val func = (x:Int) => {println("hello");println(x + x)}
    6.	     
    7.	//执行函数
    8.	func(2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    按下”Ctrl+D”,执行以上代码。输出结果如下:

    hello
    4
    
    • 1
    • 2

    2、定义函数和调用函数。
      在Scala中函数可以不依赖于类、对象、接口单独存在,函数可以作为函数的参数、返回值。
      在shell中,键入以下代码,定义函数fun1:

    1.	def fun1(name:String){
    2.	    println(name)
    3.	}
    
    • 1
    • 2
    • 3

    执行以上代码。输出结果如下:

    fun1: (name: String)Unit
    
    • 1

    将函数赋值给fun1_v:

    1.	val fun1_v = fun1 _
    
    • 1

    执行以上代码。输出结果如下:

    fun1_v: String => Unit = <function1>
    
    • 1

    调用函数fun1:

    1.	fun1("spark")
    
    • 1

    执行以下代码。输出结果如下:

    spark
    
    • 1

    调用函数fun1_v:

    1.	fun1_v("spark")
    
    • 1

    执行以上代码。输出结果如下:

    spark
    
    • 1

    下面我们定义一个名为”add”的函数,可以实现数字的相加并返回和。在paste模式下,键入以下代码:

    1.	def add(x:Int,y:Int):Int = {
    2.	    println("这是一个对两个整数进行求和的函数")
    3.	    x + y
    4.	}
    5.	     
    6.	// 通过函数名来调用函数(方法)
    7.	add(4,6)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    按下”Ctrl+D”,执行以上代码。输出结果如下:
    这是一个对两个整数进行求和的函数

    add: (x: Int, y: Int)Int
    res21: Int = 10
    
    • 1
    • 2

    3、匿名函数。
      为了使用简洁,将函数直接赋值给变量,使用函数时通过调用变量实现,称为匿名函数。
      在paste模式下,键入以下代码:

    1.	//定义匿名函数
    2.	val fun2 = (content:String) => println(content)
    3.	fun2("spark")
    
    • 1
    • 2
    • 3

    按下”Ctrl+D”,执行以上代码。输出结果如下:

    spark
    
    • 1

    8.2 高阶函数

    接收函数参数的函数,或者返回函数的函数,称为”高阶函数”。
      1、当参数为函数时。
      在paste模式下,键入以下代码:

    1.	//定义匿名函数
    2.	val hiScala = (content:String) => println(content)  
    3.	     
    4.	//定义高阶函数
    5.	def bigData(func:(String) => Unit, content:String){
    6.	    func(content)
    7.	}   
    8.	     
    9.	// 调用高阶函数
    10.	bigData(hiScala, "spark")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    按下”Ctrl+D”,执行以上代码。输出结果如下:

    spark
    
    • 1

    2、当返回值为函数时。
      在paste模式下,键入以下代码:

    1.	def func_Returned(content:String) = (message:String) => println(content + " " + message)
    2.	     
    3.	val returned = func_Returned("spark")
    4.	     
    5.	returned("scala")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    按下”Ctrl+D”,执行以上代码。输出结果如下:

    spark scala
    
    • 1

    如果在函数的函数体中,某个输入参数的值只使用了一次,此时可以将参数名称省略,用下划线“_”表示。例如,在paste模式下,键入以下代码:

    1.	// 定义函数
    2.	def spark(func:(String) => Unit, name:String){
    3.	    func(name)
    4.	}
    5.	     
    6.	// 调用函数
    7.	spark((name:String) => println(name), "scala")
    8.	     
    9.	// 类型推断
    10.	spark(name => println(name), "scala") 
    11.	     
    12.	// 进一步简化
    13.	spark(println(_), "scala")  
    14.	     
    15.	// 只有一个参数,直接省略
    16.	spark(println, "scala")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    按下”Ctrl+D”,执行以上代码。输出结果如下:

    scala
    scala
    scala
    scala
    
    • 1
    • 2
    • 3
    • 4

    3、闭包。
      当函数的变量超出其有效作用域时,仍然可以对函数内部变量进行访问,这样的函数被称为”闭包”。
      例如,在paste模式下,键入以下代码:

    1.	def scala(content:String) = (message:String) => println(content + " " + message)
    2.	     
    3.	val funcResult = scala("spark")  // 执行完毕后content的内容仍然可以被访问
    4.	funcResult("flink")  // 此时变量content的值Spark超出了函数scala的作用域,但依旧可以成功访问,即为闭包
    
    • 1
    • 2
    • 3
    • 4

    按下”Ctrl+D”,执行以上代码。输出结果如下:

    spark flink
    
    • 1

    4、函数柯里化。
      函数柯里化指的是,把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。柯里化本身也用到了闭包。
      在paste模式下,键入以下代码:

    1.	def sum(x:Int, y:Int) = x + y                //未柯里化
    2.	println(sum(1, 2))
    3.	  
    4.	def sum_Currying(x:Int) = (y:Int) => x + y    //柯里化
    5.	println(sum_Currying(1)(2))
    6.	  
    7.	def sum_Currying_better(x:Int)(y:Int) = x + y    //代码简化
    8.	println(sum_Currying_better(1)(2))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    按下”Ctrl+D”,执行以上代码。输出结果如下:

    3
    3
    3
    
    • 1
    • 2
    • 3

    5、嵌套函数
      Scala允许用户在函数中定义函数,这称为嵌套函数。其中内部函数称为局部函数。
      在paste模式下,键入以下代码:

    1.	// 函数定义
    2.	def movieAndDisplay(movieId:Int,movieName:String) = {
    3.	  
    4.	  // 局部函数定义
    5.	  def getMovieDetails(movieId:Int,movieName:String):String = {
    6.	     s" movieId是${movieId},电影名称是${movieName}"
    7.	  }
    8.	  
    9.	  // 局部函数定义
    10.	  def display{
    11.	    println(getMovieDetails(movieId,movieName))
    12.	  }
    13.	  
    14.	  // 局部函数调用
    15.	  display
    16.	}
    17.	  
    18.	// 外部函数调用
    19.	movieAndDisplay(123,"东成西就")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    按下”Ctrl+D”,执行以上代码。输出结果如下:

    movieId是123,电影名称是东成西就
    
    • 1

    9. 实验结果及分析:

    实验结果运行准确,无误

    10. 实验结论:

    经过本节实验的学习,通过学习Scala函数式编程,进一步巩固了我们的scala基础。

    11. 总结及心得体会:

    经过本节实验的学习,学习了使用Scala进行函数式编程,掌握了Scala常用高阶函数。函数式编程是用于数据分析(如Spark)的重要编程能力,必须重点掌握。
    在这里插入图片描述

  • 相关阅读:
    BIM如何通过3D开发工具HOOPS实现WEB轻量化?
    在 IIS 上构建静态网站
    文件共享服务NFS(服务名nfs,端口tcp/2049)
    怎样评测对比报表工具的性能?
    golang 并发同步(sync 库)-- 单例模式的实现(六)
    C语言自定义类型
    【金九银十必问面试题】站在架构师角度分析问题,如何解决TCC中的悬挂问题
    PyQt5快速开发与实战 7.4 事件处理机制入门 and 7.5 窗口数据传递
    最大网络流算法之dinic算法
    java中的接口
  • 原文地址:https://blog.csdn.net/qq_44807756/article/details/125551479