3、Scala基础之函数

函数的定义与调用

在Scala中定义函数时,需要定义函数的函数名、参数、函数体。
我们的第一个函数如下所示:

def sayHello(name:String, age:Int) = {
    if(age > 18) {
      printf("Hello %s, your age is %d, you are a adult\n", name, age)
    }else {
      printf("Hello %s, your age is %d, you aren't a adult\n", name, age)
    }
  }

Scala要求必须给出所有参数的类型,但是不一定给出函数返回值的类型,只要右侧的函数体中不包含递归的语句,Scala就可以自己根据右侧的表达式推断出返回类型。

多行语句的函数体

单行的函数:def sayHello(name: String) = print("Hello, " + name)
如果函数体中有多行代码,则可以使用代码块的方式包裹多行代码,代码块中最后一行的返回值就是整个函数的返回值。与Java中不同,不是使用return返回值的。
比如如下的函数,实现累加的功能:

def sum(num:Int):Int = {
    var sum = 0
    for(i <- 1 to num)
      sum += i
    sum
  }

递归函数与返回类型

如果在函数体内递归调用函数自身,则必须手动给出函数的返回类型。
例如,实现经典的斐波那契数列

  def abs(n:Int):Int = {
    if(n == 1 | n== 0) {
      1
    }else {
      abs(n - 1) + abs(n - 2)
    }
  }

默认参数

在Scala中,有时我们调用某些函数时,不希望给出参数的具体值,而希望使用参数自身默认的值,此时就定义在定义函数时使用默认参数

  def sayHello(firstName:String, middleName:String = "middle", lastName:String = "last") ={
    "hello " + firstName + " " + middleName + " " + lastName
  }

如果给出的参数不够,则会从左往右依次应用参数

Java与Scala实现默认参数的区别

java版

    public void sayHello(int age, String name){
        if(name == null) {
            name = "hello";
        }
        if(age > 18){
            System.out.println("Hello " + name +", your age is " + age + ", you are a adult");
        }else {
            System.out.println("Hello " + name +", your age is " + age + ", you aren't a adult");
        }
    }

scala版

  def sayHello(age:Int, name:String = "hello") = {
    if(age > 18){
      printf("Hello %s, your age is %d, you are a adult\n", name, age)
    }else {
      printf("Hello %s, your age is %d, you aren't a adult\n", name, age)
    }
  }

带名参数

在调用函数时,也可以不按照函数定义的参数顺序来传递参数,而是使用带名参数的方式来传递

sayHello(firstName = "tom", lastName = "lastName", middleName = "middleName")

还可以混合使用未命名参数和带名参数,但是未命名参数必须排在带名参数前面

sayHello("tom", lastName = "lastName", middleName = "middleName")

变长参数

在Scala中,有时我们需要将函数定义为参数个数可变的形式,则此时可以使用变长参数定义函数

  def sum(nums: Int*): Int = {
    var sum = 0
    for(num <- nums){
      sum += num
    }
    sum
  }

使用序列调用变长参数

在如果想要将一个已有的序列直接调用变长参数函数,是不对的。比如val s = sum(1 to 5)
此时需要使用Scala特殊的语法将参数定义为序列,让Scala解释器能够识别。这种语法非常有用!一定要好好主意,在spark的源码中大量地使用到了。
val s = sum(1 to 5: _*)
案例:使用递归函数实现累加

  def sum(nums: Int*): Int = {
    if(nums.length == 0) {
      0
    }
    else {
      nums.head + sum(nums.tail :_*)
    }
  }

过程

在Scala中,定义函数时,如果函数体直接包裹在了花括号里面,而没有使用=连接,则函数的返回值类型就是Unit。这样的函数就被称之为过程。过程通常用于不需要返回值的函数。
过程还有一种写法,就是将函数的返回值类型定义为Unit

  def sayHello(): Unit ={
    println("hello")
  }
  def sayHello() = println("hello")
  def sayHello(){println("hello")}

lazy值

在Scala中,提供了lazy值的特性,也就是说,如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算。这种特性对于特别耗时的计算操作特别有用,比如打开文件进行IO,进行网络IO等。

import scala.io.Source._
lazy val lines = fromFile("E:\\测试数据\\111.txt").mkString

即使文件不存在,也不会报错,只有第一个使用变量时会报错,证明了表达式计算的lazy特性

异常

在Scala中,异常处理和捕获机制与Java是非常相似的

try{
      throw new IllegalArgumentException("x should be negative")
    }catch{
      case _:IllegalArgumentException => println("IllegalArgumentException")
    }finally {
      println("release resource")
    }

    try{
      throw new IllegalArgumentException("user not define")
    }catch{
      case e1:IllegalArgumentException => println("IllegalArgumentException")
    }finally {
      println("release resource")
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容

  • 还记得年少时的梦吗,也许我偶尔还是会想他,偶尔难免会惦记着他,就当他是个老朋友吧。 0.1 这个城市的夏天像是患...
    就自己阅读 372评论 0 0
  • 何颖颖读书打卡 坚持读书第110天 高校教师:第七章:激发动机的训练235—237页 有感:协助学生从特殊课程过渡...
    何颖颖h阅读 110评论 0 0
  • 一、问题 Angular2中,在使用ckeitor4.x编辑器的页面中,切换到其他页面,其他页面会报警告,警告内容...
    Willworkgogogo阅读 1,401评论 0 0
  • 对接完成项目,可以歇歇了,回去搭建一个离线版的客户端,用于某展厅,老板还是让我再留一晚,研究一个继电器带wifi功...
    whIteKi阅读 230评论 0 1