暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Scala学习笔记(三)

哦呦明知山有虎 2020-07-20
379

第五章 函数式编程基础

在Scala中,「方法」「函数」几乎可以等同(比如他们的定义、使用、运行机制都是一样的)只是函数的使用方式更加的灵活多样。

函数实现是从编程方式的角度来谈的:函数式编程把函数当做一等公民,充分利用函数,支持函数的多种使用方式,既可以作为函数的参数使用,也可以将函数赋值给一个变量,函数的创建不用依赖于类或者对象,而在Java当中,函数的创建则要依赖于类、抽象类或者接口了。

5.1 基本语法

def 函数名(参数名:参数类型, ...):返回值类型 = {
   语句...
   return 返回值
}

说明:

  • 函数声明关键字为def

  • 参数名:参数类型,... 表示函数的输入(就是参数列表),可以没有。如果有,多个参数使用都好间隔

  • 函数中的语句:表示为了实现某一功能代码块

  • 函数可以有返回值,也可以没有


    • 返回值形式1;返回值类型 =
    • 返回值形式2:=表示返回值类型不确定,使用类型推导完成。
    • 返回值形式3 表示没有返回值,return不生效。
    • 如果没有热图让你,默认以执行到最后一行的结果作为返回值。

例如,使用返回值形式2展示:

object TestScala {
 def main(args: Array[String]): Unit = {
   val result = getRes(2,3,'+')
   print(result)
}
 //定义函数/方法
 def getRes(num1:Int,num2:Int,oper:Char)={
   if(oper == '-') num1-num2
   else if(oper == '+') num1+num2
   else null
}
}

结果

5

5.2 函数方法的调用机制

5.3 函数递归调用

函数递归调用的重要原则

  • 执行一个函数时,就会创建一个新的受保护的独立空间(新函数栈)
  • 函数的局部变量是独立的,不会相互影响。
  • 递归必须向退出递归的条件逼近,否则就是无限递归了。
  • 当一个函数执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁。

5.4 函数调用的注意事项

  • 函数的形参列表可以是多个,如果函数没有形参,在调用的时候可以不带().
  • 形参列表和返回值列表的数据类型可以是值类型和引用类型。
  • scala中的函数可以根据函数体最后一行代码自行推断返回值类型。那么在这种情况下,return关键字可以省略。
  • 因为scala可以自行推断,所以在省略retrun关键字的场合,返回值类型也可以省略。
  • 如果函数明确使用return关键字,那么函数返回就不能使用自行推断了,这时要明确写成:「返回类型」 =
  • 如果函数声明无返回值(声明Unit),那么函数体即使使用return关键字也不会有返回值。
  • 如果明确函数无返回值或不确定返回值类型,那么返回值类型可以省略(或声明为Any)
  • 「scala语法中任何的语法结构都可以嵌套其他的语法结构,即:函数中可以再声明定义函数,类中可以再声明类,方法中可以再声明定义方法」
  • Scala函数的形参,在声明参数时,直接赋初始值,这时调用函数时,如果没有指定实参,则会使用默认值。如果指定了实参,则实参会覆盖默认值。
  • scala函数的「形参默认值是val的」,因此不能在函数中进行修改。
  • 递归函数未执行之前是无法推断出结果类型,在使用时必须要有明确的返回值类型。
  • scala函数支持可变参数
//支持0到多个参数
def sum(args:Int*):Int = {
   
}
//支持1到多个参数
def sum(n1:Int,args:Int*):Int = {
   
}

5.5 函数过程

将函数的返回值为unit的函数称之为过程(procedure),如果明确函数没有返回值,那么等号可以省略。

def f10(name:String):Unit = {
   println(name+"hello")
}

5.6 惰性函数

惰性计算(「尽可能延迟表达式求值」)是许多函数式编程语言的特性。惰性集合在需要时提供元素,无需预先计算它们。首先,「可以将耗时的计算推迟到绝对需要的时候」。其次,「可以创造无限个集合」,只要他们继续受到请求,就会继续提供元素。函数的惰性使用能够得到更高效的代码。java并没有为惰性提供原生支持,scala提供了。

5.6.1 惰性函数介绍

当函数返回值被声明为lazy时,函数的执行将被推迟,直到首次对此取值,该函数才会执行。这种函数我们称之为惰性函数,在java的某些框架中称之为懒加载。

看下面两个例子:

非懒加载

object LazyDemo {
 def main(args: Array[String]): Unit = {
   val result = getSum(3, 6)
   //lazy val result = getSum(3, 6)
   println("******************************")
}

 //定义函数/方法
 def getSum(num1: Int, num2: Int) = {
   println("sum被执行了...")
   num1 + num2
}
}

结果

sum被执行了...
******************************

懒加载

object LazyDemo {
 def main(args: Array[String]): Unit = {
   //val result = getSum(3, 6)
   lazy val result = getSum(3, 6)
   println("******************************")
   println("result = " + result)
}

 //定义函数/方法
 def getSum(num1: Int, num2: Int) = {
   println("sum被执行了...")
   num1 + num2
}
}

结果

******************************
sum被执行了...
result = 9

注意事项:

  • lazy不能修饰var类型的变量

  • 不但是在调用函数时,加了lazy会导致函数的执行被推迟,我们在声明一个变量时,如果给声明了lazy,那么变量值的分配也会推迟。比如 lazy val i = 10

5.7 异常处理

scala提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有任意数量的try...catch块。

语法处理上和Java类似,但是又不尽相同。

scala异常捕获案例

object MyException {
 def main(args: Array[String]): Unit = {
   try {
     var r = 10/0
  }catch {
     case ex:ArithmeticException => println("捕获了除数为0的算术异常")
     case ex:Exception =>println("捕获了其他异常")
  }finally {
     println("scala finally...")
  }
}
}

结果

捕获了除数为0的算术异常
scala finally...

说明:

  1. 在scala中只有一个catch
  2. 在catch中有多个case,每个case可以匹配一种异常case ex:ArithmeticException
  3. =>关键字符号,表示后面是对该异常的处理代码块
  4. finally最终要执行的

「对于throw关键字的说明」

用throw关键字,抛出一个异常对象。所有异常都是Throwable的子类型。throw表达式是有类型的,就是Nothing,因为nothing

是所有类型的子类型,所以throw表达式可以用在需要类型的地方。


往期回顾


Scala学习笔记(一)


Scala学习笔记(二)


Spark学习笔记(一)


Spark学习笔记(二)


Spark学习笔记(三)


欢迎大家关注微信公众号:哦呦明知山有虎




文章转载自哦呦明知山有虎,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论