scala的函数式编程(一)

目录

引言

将函数作为值

匿名函数

函数的高级用法

将函数作为参数

将函数作为返回值(很重要)


引言

函数是scala中最重要的部分,有人愿意称“函数式scala中的一等公民”。也就是因为函数才使得scala更加简洁、优雅、又耐人寻味,总之,函数式编程在scala中是一等一的重要,使用scala开发的各类框架都存在这大量函数,如果想去了解、阅读Spark源码,函数式编程这一关必须要过。吹了好几行的废话,主要意思就是函数在scala中是非常重要的。下面进入正题。

将函数作为值

scala的语法规定,将函数赋值给变量时,必须在函数后面加上空格和下划线

//正常声明一个带有一个字符串类型参数,并返回Unit类型的方法
scala> def sayHello(name : String) = println("hello,"+name)
sayHello: (name: String)Unit

//将上述方法转换成一个函数,方法后面加上空格和_转变成函数
scala> val sayHelloFun = sayHello _
sayHelloFun: String => Unit = $$Lambda$1049/1571707504@210a26b

//函数的调用
scala> sayHelloFun("liumingxin")
hello,liumingxin

匿名函数

scala中可以不需要给一个函数命名,就像“y = ax + b”我们该叫它啥?其实很多时候函数并不需要一个名字,名字只是一个代号。

匿名函数的创建规则:(参数 : 参数类型) => 函数体

方法的创建规则:def 名称(参数 : 参数类型) = 函数体         

这里再提出方法的定义原因有二:1、回顾方法的创建规则;2、对比函数,理解函数和方法创建时的区别“=”和“=>”需要注意

scala> Array(1,2,3,4).map((x : Int) => x * 3)
res3: Array[Int] = Array(3, 6, 9, 12)

//可以将函数参数使用花括号代替圆括号,这样便于区分
scala> Array(1,2,3,4).map{(x : Int) => x * 3}
res4: Array[Int] = Array(3, 6, 9, 12)

在map函数内部的就是匿名函数

函数的高级用法

将函数作为参数

scala> val hello = (name : String) => println("Hello, " + name)
hello: String => Unit = $$Lambda$1178/531068784@62f3ad90

scala> val hi = (name : String) => println("hi, " + name)
hi: String => Unit = $$Lambda$1179/781449501@1a899fcd

scala> val greeting = (func : (String) => Unit , name : String) => func(name)
greeting: (String => Unit, String) => Unit = $$Lambda$1180/1925117845@1f4d9c7f

scala> greeting(hello,"liumingxin")
Hello, liumingxin

scala> greeting(hi,"liumingxin")
hi, liumingxin

 从上面代码可以看出greeting函数中第一个参数是“func : (String) => Unit”,它参数名称为"func",func参数是一个函数,这个函数参数类型为String类型,返回值为Unit类型,只要满足这两个条件,都可以作为greeting函数的第一个参数。因此greeting的类型就是"(String => Unit, String) => Unit"。

将函数作为返回值(很重要

将函数作为返回值,我当时学习这块内容的时候是相当不理解,我很疑惑对于这样一段代码:

“def greetingFunc(msg: String) = (name: String) => println(msg + ", " + name)”,又是“=”又是“=>”乱糟糟的,对于刚学scala的人来说这块阅读和使用起来相当混乱,我认为主要是写得太简练了,省略了太多东西后容易让新人过于混乱。接下来我要介绍的就是如何去理解函数作为返回值。

“def greetingFunc(msg: String) = (name: String) => println(msg + ", " + name)”的语法规则如下:

“def 方法名(参数1 : 参数类型) = (参数2 : String) => 函数体”的形式

我们来回想一下方法定义的完整形式:“def 方法名(参数 : 参数类型) : 返回值类型 = {函数体}”,例如:

scala> def greetingFunc(msg : String) : String = {println(msg + ",liumingxin");m
sg}
greetingFunc: (msg: String)String

scala> greetingFunc("hello")
hello,liumingxin
res2: String = hello

 上面代码我们先不看方法的返回值,结合“def greetingFunc(msg: String) = (name: String) => println(msg + ", " + name)”来看,“(name: String) => println(msg + ", " + name)”其实就是方法“greetingFunc(msg : String)”的函数体。理解了这一块,我们再接着往下看。

分析一下“(name: String) => println(msg + ", " + name)”,这个东东的形式是不是有点眼熟?是不是就是匿名函数啊?上面有讲。

“匿名函数的创建规则:(参数 : 参数类型) => 函数体”

scala> (name: String) => println("hello, " + name)
res4: String => Unit = $$Lambda$1057/1988962280@147ad4bb

可以看到“(name: String) => println(msg + ", " + name)”匿名函数的类型是"String => Unit",而“greetingFunc(msg : String)”方法的函数体是“(name: String) => println(msg + ", " + name)”,因此“greetingFunc(msg : String)”方法的返回类型就是“String => Unit”,表示:

“greetingFunc(msg : String)”方法返回的是一个带有String类型的参数返回值类型是Unit的函数

“greetingFunc(msg : String)”方法返回的是一个函数,这个函数式一个带有String类型的参数返回值类型是Unit的函数

看到这,我把“def greetingFunc(msg: String) = (name: String) => println(msg + ", " + name)”这种简化形式还原成完整形式

//根据函数的完整定义形式“def 方法名(参数 : 参数类型) : 返回值类型 = {函数体}”定义方法
//匿名函数的创建规则:(参数 : 参数类型) => 函数体
//“{}”中就是greetingFunc(msg : String)方法的函数体
//这个函数体就是“(name : String) => println(msg + "," + name)”,类型是“String => Unit”
//因此完整形式如下:
def greetingFunc(msg : String) : String => Unit = {(name : String) => println(msg + "," + name)}

//完整版及运行结果
scala> def greetingFunc(msg : String) : String => Unit = {(name : String) => println(msg + "," + name)}
greetingFunc: (msg: String)String => Unit

//简化版及运行结果
scala> def greetingFunc(msg: String) = (name: String) => println(msg + ", " + name)
greetingFunc: (msg: String)String => Unit

到这里我们应该能够很清晰的理解函数作为返回值这一高级特性了。

一个简单的创建和调用的例子:

scala> def greetingFunc(msg : String)= (name:String) => println(msg + "," + name)
greetingFunc: (msg: String)String => Unit

scala> val helloFunc = greetingFunc("hello")
helloFunc: String => Unit = $$Lambda$1067/709531076@71ae1cb

scala> helloFunc("liumingxin")
hello,liumingxin

这里多说几句废话,过于简洁的代码,思维跳跃性也很强,对于新人不太友好,但是函数式编程简洁的代码,能够提高开发效率,利用scala开发Spark程序的代码量比java开发的代码量少了5倍不止。scala的函数式编程是比较典型,能够掌握好scala的函数式编程,学习其他语言的函数式编程都是轻松加愉快的事情,所以这里要慢慢、细致的学习,还要加以巩固。

猜你喜欢

转载自blog.csdn.net/lazy_moon/article/details/81771402