Scala 中为什么不建议用 return 关键字
在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 关键字的更多相关文章
- Java中处理异常中return关键字
Java中,执行try-catch-finally语句需要注意: 第一:return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂 ...
- 第2节 Scala中面向对象编程:7、继承的概念以及override和super关键字;8、isInstanceOf 和 asInstanceOf关键字
6.3. Scala面向对象编程之继承 6.3.1. Scala中继承(extends)的概念 Scala 中,让子类继承父类,与 Java 一样,也是使用 extends 关键字: 继承 ...
- Programming In Scala笔记-第七章、Scala中的控制结构
所谓的内建控制结构是指编程语言中可以使用的一些代码控制语法,如Scala中的if, while, for, try, match, 以及函数调用等.需要注意的是,Scala几乎所有的内建控制结构都会返 ...
- Scala学习(五)---Scala中的类
Scala中的类 摘要: 在本篇中,你将会学习如何用Scala实现类.如果你了解Java或C++中的类,你不会觉得这有多难,并且你会很享受Scala更加精简的表示法带来的便利.本篇的要点包括: 1. ...
- Programming In Scala笔记-第十一章、Scala中的类继承关系
本章主要从整体层面了解Scala中的类层级关系. 一.Scala的类层级 在Java中Object类是所有类的最终父类,其他所有类都直接或间接的继承了Object类.在Scala中所有类的最终父类为A ...
- [转] Scala 中的异步事件处理
在任何并发性应用程序中,异步事件处理都至关重要.无论事件的来源是什么(不同的计算任务.I/O 操作或与外部系统的交互),您的代码都必须跟踪事件,协调为响应它们而执行的操作.应用程序可以采用两种基本方法 ...
- 异常处理机制中的return关键字
Java中,执行try-catch-finally语句需要注意: 第一:return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂 ...
- 大数据学习之Scala中main函数的分析以及基本规则(2)
一.main函数的分析 首先来看我们在上一节最后看到的这个程序,我们先来简单的分析一下.有助于后面的学习 object HelloScala { def main(args: Array[String ...
- scala学习手记16 – scala中的static
前面两节学了scala的对象和伴生对象,这两个在使用的时候很有些java的静态成员的意思. scala中没有静态字段和静态方法.静态成员会破坏scala所支持的完整的面向对象模型.不过可以通过伴生对象 ...
随机推荐
- 「Spring Boot 2.4 新特性」启动耗时详细监控
背景 Spring Boot 项目随着项目开发过程中引入中间件数量的增加,启动耗时 逐渐增加. 笔者在 <Spring Boot 2.4.0 正式 GA,全面拥抱云原生>文章评论下发现了 ...
- 承接上一篇,whale系统开篇,聊聊用户认证
写在前面 上次老猫和大家说过想要开发一个系统,从简单的权限开始做起,有的网友表示还是挺支持的,但是有的网友嗤之以鼻,认为太简单了,不过也没事,简单归简单,主要的还是个人技术的一个整合和实战. 没错,系 ...
- Tensorflow Serving 参数
Flags: --port=8500 int32 Port to listen on for gRPC API --grpc_socket_path="" string If no ...
- C语言-字符串函数的实现(二)之strcpy
C语言中的字符串函数有如下这些 获取字符串长度 strlen 长度不受限制的字符串函数 strcpy strcat strcmp 长度受限制的字符串函数 strncpy strncat strncmp ...
- 超详细!!Spring5框架开发笔记
Spring5开发教程 简介 spring特性 sping是轻量级的开源的JavaEE框架 Spring可以解决企业应用开发的复杂性 Sping两个核心的部分:IOC和AOC IOC:控制反转.把创建 ...
- kubernetes集群EFK日志系统搭建
日志收集架构 Kubernetes 集群本身不提供日志收集的解决方案,一般来说有主要的3种方案来做日志收集: 在节点上运行一个 agent 来收集日志 在 Pod 中包含一个 sidecar 容器来收 ...
- 中文NER的那些事儿1. Bert-Bilstm-CRF基线模型详解&代码实现
这个系列我们来聊聊序列标注中的中文实体识别问题,第一章让我们从当前比较通用的基准模型Bert+Bilstm+CRF说起,看看这个模型已经解决了哪些问题还有哪些问题待解决.以下模型实现和评估脚本,详见 ...
- wordpress 自定义路由及展示页
wordpress 自定义路由及展示页 注册domain/test这个路由 wordpress 有重写url的方法,叫 add_rewrite_rule().在function.php中加入如下代码段 ...
- DVWA之File Inclusion
File Inclusion File Inclusion,意思是文件包含(漏洞),是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数(include(),req ...
- WindowsPE 第五章 导出表
导出表 PE中的导出表存在于动态链接库文件里.导出表的主要作用是将PE中存在的函数导出到外部,以便其他人可以使用这些函数,实现代码重用. 5.1导出表的作用 代码重用机制提供了重用代码的动态链接库,它 ...