Scala高阶函数

本文详细介绍了Scala中的高阶函数,包括匿名函数的使用,将函数作为参数传递给其他函数以及函数返回值为函数的情况。此外,文章还深入探讨了柯里化概念并提供了代码示例。接着,文章讨论了Scala的隐式转换,包括隐式值、隐式类、隐式转换的时机以及隐式解析机制,解释了隐式转换的规则和前提条件。
摘要由CSDN通过智能技术生成

匿名函数

而在大量的spark中大都用的是匿名函数(不为函数命名),然后将其复制个一个变量。

如:
这里写图片描述

 匿名函数格式:
Val 变量名 = (参数:类型) => 函数体

高阶函数

函数参数

1.将函数做参数传给另一个函数

如:
这里写图片描述

  • 首先我们定义了一个函数BigData,这个函数有两个参数,第一个参数是一个函数,函数名是func,他有一个String类型的参数并且返回值是unit空的;第二个参数是String类型的变量名为content的变量,函数体是将第二个参数作为第一个参数也就是函数func的参数,来调用第一个函数,整个函数返回值为unit空。这里只要传入的函数的格式与定义的一致就行。
    又如:

这里写图片描述

  • Array.map()作用,他会遍历array中每一个元素,并将每个元素作为具体的值传给map中的作为参数的函数。
2.函数的返回值是函数

这个函数也是一样,只要理解了返回值是类型一个匿名函数就行了。

def addBy(factor:Int) = {
  (x:Double)=> factor + x
}

(x:Double) 是返回函数的参数定义,返回类型由表达式 factor +x 来决定。如果表达式比较复杂,也可以如下写法

(x:Double)=> { do some things }

我们看看如何调用函数

package com.dt.scala.hello
import scala.math._
object ScalaInAction {
    def addBy(factor:Int) = {
      (x:Double)=> factor + x
    }  //> addBy: (factor: Int)Double => Double
 
    val addFive = addBy(5) //> addFive  : Double => Double = <function1>
    println(addFive(20)) 

柯里化

柯里化指的是将原来接受两个参数的方法变成新的接受一个参数的方法的过程

这里写图片描述


代码

object CurringFuncTest { def main(args: Array[String]): Unit = { //正常定义1 def multiple1(x:Int,y:Int) = x*y println(multiple1(2,3)) //其中一个函数作为返回值 def multiple2(x:Int)=(y:Int)=>x*y println(multiple2(3)(4)) //柯里化 def multiple3AfterCurring(x:Int)(y:Int) = x*y println(multiple3AfterCurring(4)(5)) //必须传递两个参数,否则编译报错 val a = Array("XX","YY") val b = Array("xx","yy") println(a.corresponds(b)(_.equalsIgnoreCase(_))) } }

2、结果

6
12
20
true

隐式转换

当Scala编译器进行类型匹配时,如果找不到合适的候选,那么隐式转化提供了另外一种途径来告诉编译器如何将当前的类型转换成预期类型。

使用方式:

1.将方法或变量标记为implicit
2.将方法的参数列表标记为implicit
3.将类标记为implicit


Scala支持两种形式的隐式转换:

隐式值:用于给方法提供参数
隐式视图:用于类型间转换或使针对某类型的方法能调用成功

隐式值:

例1:声明person方法。其参数为name,类型String

scala> def person(implicit name : String) = name  //name为隐式参数
person: (implicit name: String)String

直接调用person方法

scala> person
<console>:9: error: could not find implicit value for parameter name: Stringperson

报错!编译器说无法为参数name找到一个隐式值

定义一个隐式值后再调用person方法

scala> implicit val p = "mobin"  //p被称为隐式值
p: String = mobin
scala> person
res1: String = mobin

因为将p变量标记为implicit,所以编译器会在方法省略隐式参数的情况下去搜索作用域内的隐式值作为缺少参数。
但是如果此时你又在REPL中定义一个隐式变量,再次调用方法时就会报错

scala> implicit val p1 = "mobin1"
p1: String = mobin1
scala> person
<console>:11: error: ambiguous implicit values:
both value p of type => String
and value p1 of type => String
match expected type String  person

匹配失败,所以隐式转换必须满足无歧义规则,在声明隐式参数的类型是最好使用特别的或自定义的数据类型,不要使用Int,String这些常用类型,避免碰巧匹配

隐式类:
在scala2.10后提供了隐式类,可以使用implicit声明类,但是需要注意以下几点:

1.其所带的构造参数有且只能有一个
2.隐式类必须被定义在类,伴生对象和包对象里
3.隐式类不能是case class(case class在定义会自动生成伴生对象与2矛盾)
4.作用域内不能有与之相同名称的标示符

object Stringutils { implicit class StringImprovement(val s : String){ //隐式类 def increment = s.map(x => (x +1).toChar) } } object Main extends App{ import com.mobin.scala.implicitPackage.Stringutils._ println("mobin".increment) }

编译器在mobin对象调用increment时发现对象上并没有increment方法,此时编译器就会在作用域范围内搜索隐式    实体,发现有符合的隐式类可以用来转换成带有increment方法的StringImprovement类,最终调用increment方法。

隐式转换的时机:

1.当方法中的参数的类型与目标类型不一致时
2.当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换


隐式解析机制

即编译器是如何查找到缺失信息的,解析具有以下两种规则:
1.首先会在当前代码作用域下查找隐式实体(隐式方法 隐式类 隐式对象)
2.如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找
类型的作用域是指与该类型相关联的全部伴生模块,一个隐式实体的类型T它的查找范围如下:
(1)如果T被定义为T with A with B with C,那么A,B,C都是T的部分,在T的隐式解析过程中,它们的伴生对象都会被搜索
(2)如果T是参数化类型,那么类型参数和与类型参数相关联的部分都算作T的部分,比如List[String]的隐式搜索会搜索List的
伴生对象和String的伴生对象
(3) 如果T是一个单例类型p.T,即T是属于某个p对象内,那么这个p对象也会被搜索
(4) 如果T是个类型注入S#T,那么S和T都会被搜索

隐式转换的前提:

1.不存在二义性
2.隐式操作不能嵌套使用(如 convert1(covert2(x)))+y
3.代码能够在不使用隐式转换的前提下能编译通过,就不会进行隐式黑铁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值