美文网首页
Spark(十) Spark源码阅读函数式编程知识点

Spark(十) Spark源码阅读函数式编程知识点

作者: 文子轩 | 来源:发表于2018-10-28 17:31 被阅读34次

一、函数和方法

  • Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。
  • Scala 中使用 val 语句可以定义函数,def 语句定义方法
//定义一个方法
def sum(a:Int, b:Int) = a + b
//因为方法即操作符,所以在调用方法时有时可以省略括号,而函数必须带上括号
//例如加号+就是一个方法,a + b也可以写成a.+(b)
定义一个函数
val sum2 = (a: Int, b: Int) => a + b
  • 方法不能作为参数进行传递调用!!!,函数因为是对象所以可以作为参数进行传递!!!
  • 3,但是Scala中可以把方法转换成函数
//后面加下划线可以把方法转换成函数,注意要有空格
sum _
  • 注:直接传方法也可以运行,Scala会自动将其转换成函数
def sum(a: Int, b: Int): Int = a.+(b)

  val sum2 = (a: Int, b: Int) => a + b

  def fn(f: (Int, Int) => Int) = {
    println(f(3, 10))
  }

  def main(args: Array[String]): Unit = {
    fn(sum)//输出13,Scala会自动将sum方法转换成函数
    fn(sum2)//输出13
  }

二、scala中的匿名函数

Scala提供了一个相对轻量级的语法来定义匿名函数。源代码中的匿名函数称为函数文字,在运行时,函数文字被实例化为称为函数值的对象。

val fun2 = (content:String) =>println(content)
var userDir = () => { System.getProperty("user.dir") }

三、高阶函数

1、scala的高阶函数:把函数当做参数传入到另一个函数中,函数的参数是函数


scala> val sayHello = (name: String) => println("my name is:" + name)
sayHello: String => Unit = <function1>
 
scala> sayHello("cyony")
my name is:cyony
 
scala>   def introduce(fun: (String) => Unit, name: String, age: Int): Unit = {
     |     println("my age is:"+age)
     |     fun(name)
     |   }
introduce: (fun: String => Unit, name: String, age: Int)Unit
 
scala> introduce(sayHello,"cyony",25)
my age is:25
my name is:cyony

上面一步定义了匿名函数,且赋值给了sayHello变量。然后定义了一个introduce函数,他的签名为,第一参数为一个方法,此fun的签名为一个String变量,返回类型是Unit;第二个参数是一个String类型的变量;第三个参数是Int类型的变量。因为fun变量自己就是一个函数,且又传给了introduce函数,所以称fun为他的高阶函数。在调用的时候,为fun传入sayHello变量,最终打印结果如上所示。

2、函数的返回值就是一个函数:函数的返回值是函数 == 有返回高阶函数

scala> def introduce(age: Int) = (name: String) => println("my name is:" + name + ",my age is:" + age)
introduce: (age: Int)String => Unit
 
scala>  val introduceFun = introduce(25)
introduceFun: String => Unit = <function1>
 
scala> introduceFun("cyony")
my name is:cyony,my age is:25

这个例子和上面的相比,有点不同,introduce函数本身返回的也是一个函数,可以看到repl的提示,返回一个签名为String,返回为Unit的匿名函数,函数主体则是打印那句话。在调用的时候,首先得到这个匿名函数,然后再调用这个匿名函数。这个匿名函数同样是introduce的高阶函数。

四、科里化

example

是指一个函数有两个参数,可以将一个函数转换成两个函数:第一个函数是第一个参数。第二个函数是接收第二个参数
def sum(x:Int, y:Int) = x +y
等价于
def sum_Currying(x:Int) = (y:Int) =>x+y  等价于def sum_Currying(x:Int) (y:Int) =x+y 
sum_Currying(1)(2)

Currying函数

scala> def introduce(age: Int)(name: String) = println("my name is:" + name + ",my age is:" + age)
introduce: (age: Int)(name: String)Unit
 
scala> introduce(25)("cyony")
my name is:cyony,my age is:25

函数的currying化行为本质上也是一个高阶函数:接受现有的函数,返回新函数。 这个例子就是对上一个例子的currying化操作。传入第一个参数后返回一个函数,然后再传入第二个参数,完成第二个函数。这样就讲一个高阶函数拆解成两个一阶函数。

高阶函数类型推断

scala>   def triple(fun: (Int) => Int, num: Int) = {
     |     fun(num)
     |   }
triple: (fun: Int => Int, num: Int)Int
 
scala> triple(_*3,5)
res12: Int = 15

如上所示,定义了一个triple函数,他的签名是一个高阶函数和一个整形。在这个函数实际使用的时候,用了占位符来替换传入参数,因为传入的参数肯定是Int类型,且在此主体中只使用了一次,所以可以直接用占位符表示,省去了函数签名以及返回,直接定义主体,使得语法非常精简。

五、函数闭包

闭包的方式:函数超出了自己的作用域的时候,内部的变量依然可以访问外部。

1,闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
2,一旦函数引用了外部的变量或常量,那么就称此函数为闭包函数。

  val x = 3
  val fn = (y: Int) => x + y//闭包
(x:Int) => println(x+10)  //不是闭包。

相关文章

网友评论

      本文标题:Spark(十) Spark源码阅读函数式编程知识点

      本文链接:https://www.haomeiwen.com/subject/ijqmtqtx.html