在scala中使用 return 的话,编译的时候会提示the latest statement is method is automatically returned, use of th return keyword is redundant.

这个警告是说最后一个语句的结果会自动返回,不需要使用return语句。 scala 不建议使用 return 关键字,这一点在刚刚接触函数式编程的时候感觉非常难受。

有 return 会让代码结果更清晰不是么?在查阅之后,整理了以下几点不建议使用 return 关键字的原因。

1.要写函数而不是指令

函数式编程的一个重要理念就是要尽量使代码由无状态的函数构成,而不是给计算机发出指令。例如

f(x) = x + 1    //式1.1
1

是一个函数。

scala会自动将最后一个表达式的结果作为返回结果

def f(x:Int) = x + 1    //式1.2
def f(x:Int):Int = return x + 1 //式1.3
12

从以上两种分别使用和不使用 return 的表达方式来看,不使用 return 看起来更接近函数,而使用了 return 则更像指令。

2.return影响类型推断

scala中的类型推断机制会自动将最后一个表达式的类型作为返回类型,例如式1.2中,函数能够自动识别结果为Int类型。如果使用了return语句,就会破坏类型推断机制,需要显式注明返回类型,例如式1.3。

3.使用return返回含义模糊

有时使用了return会让代码的返回更加混乱,这个歧义主要产生于return到底返回到哪一层函数。

def add(n:Int, m:Int): Int = return n + m     //式3.1
def sum1(ns: Int*): Int = ns.foldLeft(0)(add) //式3.2
12

例如上述代码,目前来看还没有什么问题,但是如果写成下面的形式

def sum2(ns: Int*): Int = ns.foldLeft(0)((n,m) => return n+m)    //式3.3
1

直观感受式3.3与3.1+3.2应该是等效的。但事实上sum1(1,2,3) = 6,而sum2(1,2,3) = 1.

原因就是return语句会直接让它所出现的函数返回。也就会直接break foldLeft的循环返回结果。

再看另外一个例子:

def foo: Int = {
val sumR: List[Int] => Int = _.foldLeft(0)((n, m) => return n + m)
sumR(List(1,2,3)) + sumR(List(4,5,6))
}
1234

首先定义一个匿名函数,在调用匿名函数的时候,相当于return语句出现在了foo函数中。因此foo() = 1

4.NonLocalReturnControl

在scala的循环中的return实际上是通过抛异常实现的,编译后发现

return value
1

被编译成了

throw new NonLocalReturnControl(key/*metadata*/, value)
1

而NonLocalReturnControl的源码为:

class NonLocalReturnControl[@specialized T](val key: AnyRef, val value: T) extends ControlThrowable {
final override def fillInStackTrace(): Throwable = this
}
123

可以看到NonLocalReturnControl异常继承了Throwable,并且为了提升性能重写了fillInStackTrace不填入堆栈信息。这样一来,如果我们在代码中为了保护代码不crash而这样写:

def fun(n:Int):String = {
try {
for(i <- 0 to n){
if(i < 5){
}else{
return "gt"
}
}
""
}catch{
case t:Throwable => return t.toString
}
}
12345678910111213

最终得到的结果字符串则为scala.runtime.NonLocalReturnControl,并不是我们预期的结果。

5.应当怎么做

实际开发中我们会经常遇到貌似必须使用return的时候,那应该怎么办呢?

首先,scala既然提供了 return 关键字,说明它并不是禁止使用,而是需要考虑清楚是否必须这么做。在scala认为,所有的需要使用 return 来 break 的循环,都是可以通过转化为递归来替代的,并且性能方面 scala 也专门为递归做了优化。

Scala 中为什么不建议用 return 关键字的更多相关文章

  1. Java中处理异常中return关键字

    Java中,执行try-catch-finally语句需要注意: 第一:return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂 ...

  2. 第2节 Scala中面向对象编程:7、继承的概念以及override和super关键字;8、isInstanceOf 和 asInstanceOf关键字

    6.3.   Scala面向对象编程之继承 6.3.1.     Scala中继承(extends)的概念 Scala 中,让子类继承父类,与 Java 一样,也是使用 extends 关键字: 继承 ...

  3. Programming In Scala笔记-第七章、Scala中的控制结构

    所谓的内建控制结构是指编程语言中可以使用的一些代码控制语法,如Scala中的if, while, for, try, match, 以及函数调用等.需要注意的是,Scala几乎所有的内建控制结构都会返 ...

  4. Scala学习(五)---Scala中的类

    Scala中的类 摘要: 在本篇中,你将会学习如何用Scala实现类.如果你了解Java或C++中的类,你不会觉得这有多难,并且你会很享受Scala更加精简的表示法带来的便利.本篇的要点包括: 1. ...

  5. Programming In Scala笔记-第十一章、Scala中的类继承关系

    本章主要从整体层面了解Scala中的类层级关系. 一.Scala的类层级 在Java中Object类是所有类的最终父类,其他所有类都直接或间接的继承了Object类.在Scala中所有类的最终父类为A ...

  6. [转] Scala 中的异步事件处理

    在任何并发性应用程序中,异步事件处理都至关重要.无论事件的来源是什么(不同的计算任务.I/O 操作或与外部系统的交互),您的代码都必须跟踪事件,协调为响应它们而执行的操作.应用程序可以采用两种基本方法 ...

  7. 异常处理机制中的return关键字

    Java中,执行try-catch-finally语句需要注意: 第一:return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂 ...

  8. 大数据学习之Scala中main函数的分析以及基本规则(2)

    一.main函数的分析 首先来看我们在上一节最后看到的这个程序,我们先来简单的分析一下.有助于后面的学习 object HelloScala { def main(args: Array[String ...

  9. scala学习手记16 – scala中的static

    前面两节学了scala的对象和伴生对象,这两个在使用的时候很有些java的静态成员的意思. scala中没有静态字段和静态方法.静态成员会破坏scala所支持的完整的面向对象模型.不过可以通过伴生对象 ...

随机推荐

  1. JavaScript深入理解-PWA渐进式应用

    WPA-渐进式 web 应用 PWA 是什么 渐进式 Web 应用,提升 web app 浏览体验. manifest 应用程序清单 基本介绍: web app manifest是 PWA 技术集合中 ...

  2. 【笔记】《Redis设计与实现》chapter9 数据库

    9.1 服务器中的数据库 Redis服务器将所有都保存在服务器状态redis.h/redisServer结构中 struct redisServer{ //... // 一个数组,保存着服务器中所有数 ...

  3. 记一次 .NET游戏站程序的 CPU 爆高分析

    一:背景 1. 讲故事 上个月有个老朋友找到我,说他的站点晚高峰 CPU 会突然爆高,发了两份 dump 文件过来,如下图: 又是经典的 CPU 爆高问题,到目前为止,对这种我还是有一些经验可循的. ...

  4. JS 中一些高效的魔法运算符

    这两天有同事说我挺久没更新文章了,不过最近一段时间确实有点忙,一直在忙着两个活动中心的改版,没什么时间来更新文章.今天终于抽空可以写一写. JavaScript 现在每年都会发一个新版本,里面也会新增 ...

  5. [BUAA2021软工助教]案例分析作业总结

    目录 一.作业链接 二.优秀作业推荐 A+作业推荐 A作业推荐 三.总结 所有案例分析总结 特色与优点 问题与建议 不同类产品案例分析Bug汇总 CSDN问答社区.Stack Overflow.Seg ...

  6. 1149 Dangerous Goods Packaging

    When shipping goods with containers, we have to be careful not to pack some incompatible goods into ...

  7. sed高级指令

    N命令 n命令 n命令简单来说就是提前读取下一行,覆盖模型空间前一行,然后执行后续命令.然后再读取新行,对新读取的内容重头执行sed //从test文件中取出偶数行 [root@localhost ~ ...

  8. C++ 2.0新特性

    C++ standard之演化 C++ 98(1.0) C++ 03(TR1, technical Report 1) // 一个实验性的版本 C++ 11(2.0) C++ 14 此次记录涵盖了C+ ...

  9. uni-app&H5&Android混合开发一 || 最全面的uni-app离线打包Android平台教程

    前言: 为什么会写这么一个教程,因为很久之前做过一个对接银行POS我们的系统是使用的H5开发的app应用.但是假如对结果银行相关业务的小伙伴应该都清楚,银行的业务相对于其他的对接方而言安全性比较高,而 ...

  10. 分享几个网址二维码生成api

    分享几个网址二维码生成api 传入网址参数,或许二维码图片,扫二维码能直接跳转网址 http://b.bshare.cn/barCode?site=weixin&url=https://www ...