首页 > 代码库 > Scala函数式编程进阶
Scala函数式编程进阶
1 package com.dtspark.scala.basics 2 3 /** 4 * 函数式编程进阶: 5 * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量; 6 * 2, 函数更长用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要名称,但是如果你要使用的话,一般会把这个匿名函数赋值给一个变量(其实是val常量),Spark源码中大量存在这种语法,必须掌握; 7 * 3, 函数可以作为参数直接传递给函数,这极大的简化的编程的语法,为什么这样说呢?原因非常简单: 8 * 第一:以前Java的方式是new出一个接口实例,并且在接口实例的回调方法callback中来实现业务逻辑,现在是直接把回调方法callback传递给我的函数,且在函数体中直接使用,这毫无疑问的简化的代码的编写,提升了开发效率; 9 * 第二:这种方式非常方便编写复杂的业务逻辑和控制逻辑,对于图计算、机器学习、深度学习等而言至关重要; * 10 * 函数作为函数的参数传递的编程方式是称之为高阶函数的编程方式,Spark源码和应用程序开发中至少60%都是这种代码,必须务必一定要掌握。11 * 4, 函数式编程一个非常强大的地方之一在于函数的返回值可以是函数,当函数的返回类型是函数的时候,这个时候就表明Scala的函数实现了闭包!12 * Scala闭包的内幕是:Scala的函数背后是类和对象,所以,Scala的参数都作为了对象的成员!!!!!!,所以后续可以继续访问,这就是Scala实现闭包的原理内幕! * 13 * 5, Currying, 复杂的函数式编程中经常使用,可以维护变量在内存中的状态,且实现返回函数的链式功能,可以实现非常复杂的算法和逻辑;14 */15 object functionalProgramming {16 def main(args: Array[String]): Unit = {17 /**18 * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量;19 */20 val hiData =http://www.mamicode.com/ hiBigData _21 hiData("Spark")22 23 /**24 * 2, 函数更长用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要名称,但是如果你要使用的话,一般会把这个25 * 匿名函数赋值给一个变量(其实是val常量),Spark源码中大量存在这种语法,必须掌握;26 */27 val f = (name: String) => println("Hi, " + name)28 f("Kafka")29 30 31 /**32 * * 3, 函数可以作为参数直接传递给函数,这极大的简化的编程的语法,为什么这样说呢?原因非常简单:33 * 第一:以前Java的方式是new出一个接口实例,并且在接口实例的回调方法callback中来实现业务逻辑,现在是直接把回调方法callback传递给我的函数,且在函数体中直接使用,这毫无疑问的简化的代码的编写,提升了开发效率;34 * 第二:这种方式非常方便编写负责的业务逻辑和控制逻辑,对于图计算、机器学习、深度学习等而言至关重要; 35 * 函数作为函数的参数传递的编程方式是称之为高阶函数的编程方式,Spark源码和应用程序开发中至少60%都是这种代码,必须务必一定要掌握。36 */37 def getName(func: (String) => Unit, name: String){38 func(name)39 }40 getName(f,"Scala") 41 Array(1 to 10: _*).map { (item: Int) => 2 * item }.foreach { x => println(x) }42 43 /**44 * 4, 函数式编程一个非常强大的地方之一在于函数的返回值可以是函数,当函数的返回类型是函数的时候,这个时候就表明Scala的函数实现了闭包!45 * Scala闭包的内幕是:Scala的函数背后是类和对象,所以,Scala的参数都作为了对象的成员!!!!!!,所以后续可以继续访问,这就是Scala 46 * 实现闭包的原理内幕!47 */48 def funcResult(message: String) = (name: String) => println(message + " : " + name)49 //def funcResult(message: String, name: String){println(message + " : " + name)}50 51 funcResult("Hello")("Java") //Currying函数写法, 必须掌握这种写法,只要是复杂的Scala函数式编程代码就一定会使用这种写法52 val result = funcResult("Hello")53 result("Java") 54 }55 56 def hiBigData(name: String){57 println("Hi, " + name)58 }59 60 }
2.补充知识
a.代码中第一点有一句
val hiData = http://www.mamicode.com/hiBigData _ 这里_将hiBigData 转成了函数
在Scala中,无法直接操纵方法,只能直接操纵函数,所以需要使用_。
b.代码中第二和第三点
val f = (name: String) => println(“Hi, ” + name) 调用时直接f(“Kafka”)容易理解。
但是 getName(f,”Scala”) 调用时这里f 是没参数的!
def getName(func: (String) => Unit, name: String){
func(name)
}
这里getName第一个参数是函数,输入类型为String,无返回值。所以这里第一个参数是函数,而开始学的时候,我一直不理解为什么没有括号,像这样 getName(f(“xx”),”Scala”),仔细想过之后才知道f(“xx”)不是函数,而是一个Unit,而要求的是(String)=>Unit!也就是说函数作为参数传入时是不能加括号的!!!
函数中如果函数作为参数传入,有两种调用方式,第一种是上面那种,先定义一个函数值,如
val f = (name: String) => println(“Hi, ” + name) ,这里也可用def f(name: String){println(“Hi, ” + name)},然后传入名称就行。第二种是直接写入匿名函数,如这里也可以改为 getName((name: String) => println(“Hello, ” + name) , “Spark”)
个人感觉难点还是在传入函数与函数之间的如何使用才是难点!
c.闭包
什么是闭包? funcResult(“Hello”)(“Java”)中”Hello”是第一个参数,”Java”是第二个参数,正常情况下一个函数参数是不会保存下来的,因为这里是没有创建对象,如果要保存下来得这样吧:val some = “Hello”,定义个内存空间给他,然后funcResult(some)这样。但是例子中是保存下来了,保存在哪里?可以理解为像funcResult这种函数作为函数返回值的类型里面有一个小地方用为保存参数的,而这个函数看作两个函数,一旦程序运行时第一个函数会先得到一个参数,然后会保存起来,后面的第二个函数能拿到这个参数来继续使用(越说越不清了 -_-!)。
Scala函数式编程进阶