就是个控制结构,Scala 能有什么新花样呢?

news/2024/7/7 18:46:42

1992430611efeb9bb7b3729bcd3a1c1f.gif

作者 | luanhz

来源 | 小数志

导读

编程语言中最为基础的一个概念是控制结构,几乎任何代码都无时无刻不涉及到,其实也就无外乎3种:顺序、分支和循环。本文就来介绍Scala中控制结构,主要是分支和循环。

Scala中的控制结构实质上与其他编程语言并无太大差别,需要注意的是Scala中的控制结构大多具有返回值,而其他编程语言中的控制结构一般就仅仅是用于流程控制。本文主要目录如下:

  • 分支结构

    • if-else

    • match-case

  • 循环结构

    • for循环

    • while循环

    • do-while循环

    • break和continue

01 分支结构

分支结构应该编程中最为常用的控制结构了,典型的if-else也是最能代表程序员思维的了。这里首先插一个只有程序员才懂的段子:

女朋友对程序员说:“亲爱的,去超市买一个西瓜吧,如果他们还有鸡蛋,再买20个”,结果程员带了21个西瓜回家。女朋友愤怒地说:“为什么买21个西瓜回来”?程序员答:“因为他们确实有鸡蛋”。

这个冷笑话,其实质就是一个顺序结构+选择分支结构。那么在Scala中,分支结构当然也是用关键字if-else,更具体的说无外乎以下3种形式:

scala> val num = 2
val num: Int = 2
// 单分支
scala> if(num>1) print("greater")
greater
// 双分支
scala> if(num>1) print("greater") else print("less")
greater
// 多分支
scala> if(num>2) print("greater") else if(num==2) print("equal") else print("less")
equal

if-else是最常规的分支选择结构,Scala中也不例外。另外,除了以上三种形式外,当然还可以组织嵌套的if-else结构,但实质都是一样。形式虽然一样,但Scala中其实也有其特别之处:那就是Scala中的if-else其实应当理解成一个代码块,而在Scala中但凡是代码块,基本上都对应有返回值,所以无论是单分支、双分支还是多分支,其返回值就是相应分支的结果,虽然这个返回结果可能为Unit,例如上述print语句后其实就并未产生实际的返回值。同时需指出的是,在单分支中只有if单条语句,当条件不满足时实际上也是对应控制的返回结果。

正因为if-else都是有返回值的,所以Scala中并未设立像其他语言中那样的三元选择运算符,而是交由if-else完成这一功能。

除了if-else这种经典的分支结构外,编程语言中另一经典分支结构是switch-case结构,这在Scala中也是有所体现的,只不过未提供switch,而是支持功能更为强大的模式匹配:match-case,甚至有人将其称作是最能体现Scala特色和优势的特性之一。本文作为系列入门文章,仅就其实现最基础的分支结构做以说明。

scala> num match{  // match 关键字case x if(x<0) => print("<0")  // 代入条件判断case 0 => print("0")  // 直接以具体值判断case 1 => print("1")case _ => print("other") // 用_表示其他情况}
other

注:模式匹配在Scala中仍属于一个代码块,也是有返回值的。

在模式匹配中另外值得关注的一个细节是,在各匹配分支后,用映射符号"=>"连接条件和执行逻辑,这与Scala中函数的标志性符号是一致的,都表示映射的含义,一定程度上也暗示着模式匹配其实可理解为根据条件逻辑执行一个个的子函数。

02 循环结构

除了选择分支结构,程序中另外一个常用的循环。实话说,循环常常是在解决很多算法题目时最先想到的方案,虽然效率不高,但却非常简单粗暴和直观易懂。通常情况下,循环有3种结构:

  • for

  • while

  • do……while

Scala也不例外,而结合Scala的特性,这三种循环往往有着更为优雅的运用。

1)for循环。Scala中的for循环其实与Python中的for循环比较类似,通常用法是将一个可迭代对象逐一赋值给循环变量,完成相应操作的过程。最基础的用法如下:

scala> for(i <- 1 to 3) println(i)
1
2
3

在for循环内部,还可以直接嵌套逻辑判断条件,术语说法叫做循环守卫,即仅当条件满足时才进入循环体执行,否则进入下一循环:

scala> for(i <- 1 to 3 if(i%2==1)) print(i)
1
3

除了嵌套逻辑条件判断,还可以增加一些附属操作,仅仅是为了便于后续循环体执行,对循环执行不产生任何影响:

scala> for(i <- 1 to 3; j=2*i) println(j)
2
4
6

注意在循环变量与附属操作之间,需用";"做以分割,表示这是两句代码。而在前述的循环守卫中则可加可不加,且一般情况下不加";"更为直观。

对于嵌套循环,除了类似其他编程语言中的书写两重for循环外,还可直接将两层循环变量写到一个for循环中,功能一致但逻辑更为清晰:

// 嵌套for循环常规写法
scala> for(i <- 1 to 3) for(j <- 1 to i) println(i*j)
1
2
4
3
6
9
// 精简写法
scala> for(i <- 1 to 3; j <- 1 to i) println(i*j)
1
2
4
3
6
9

for循环在Scala中仍然属于一个代码块,所以其实也是有返回值的。应用这一特性,for循环其实还有另一个巧妙的运用:由一个迭代器生成另一个迭代器,功能类似于Python中的列表推导式。实现这一功能,需要配合使用关键yield:

scala> val nums = (for(i <- 1 to 5) yield i*2).toList
val nums: List[Int] = List(2, 4, 6, 8, 10)

2)while循环。一般而言,对于具有明确次数的循环结构采取for循环比较合适,而对于循环次数未知、需根据循环执行结果判断是否继续执行的情况则选用while循环更为合适。Scala中的while循环与其他编程语言中while用法几乎完全一致:

scala> var sum = 0
var sum: Int = 0scala> var i = 0
var i: Int = 0scala> while(sum<10){println(i); sum+=i; i+=1}
0
1
2
3
4

不过,除了使用场景的不同,Scala中while循环与for循环的另一个技术细节上的区别在于:for循环作为一个代码块是有对应返回值的(虽然可能返回值可能为空),而while循环则一定没有返回值(或者说返回值一定为空)。这一区别意味着:for循环既可以用于迭代产生新的迭代结果,也可以依靠历次循环产生相应的效果(即执行循环体带来副作用),而while循环则只能靠循环产生的副作用来实现功能。例如,模拟前面使用for循环+yield产生新的迭代器的过程,强行使用while循环实现如下:

scala> val arr = new Array[Int](3)
val arr: Array[Int] = Array(0, 0, 0)scala> var i = 1
var i: Int = 1scala> while(i<=3) {arr(i-1) = i*2; i+=1}scala> arr
val res3: Array[Int] = Array(2, 4, 6)

3)do……while循环。do……while循环在实际工作中使用还是比较少的,其使用方法与while循环十分类似,唯一的区别在于while循环是先判断后执行;而do……while循环则是先执行再判断,所以无论如何do……while会至少执行一次。

最后值得指出的是,与其他编程语言不同,在Scala中并没有break和continue两个关键字,即无法简单实现循环中止或者跳过本次循环这一逻辑。虽然取以代之提供了break()方法,但用起来终究还是不够方便。那如果就是要实现break和continue两个需求呢,实际上Scala中可以灵活选用如下3种方式:

  • 增加if条件判断

  • for循环中设置循环守卫

  • while循环中增加相应的判断逻辑

03 小结

控制结构是编写任何程序都不得不涉及到的一个概念,对于常用的分支结构、循环结构在Scala中都有所体现,且均具有一定特色,灵活掌握还是比较方便的。

fd3101ca82d4078425aa1510a483688a.gif

25736cd48d3154b772291d2762a8cbcf.png

资讯

Meta开发AI语音助手,助力元宇宙

技术

霸占CSDN榜一的20个Python用例

技术

20个Pandas数据实战案例,干货多

资讯

安全隐患:神经网络可以隐藏恶意软件

775fc513496fd35bf2748d37d22b0ea5.png

分享

6a25169c5f73955cfd733214c755b34e.png

点收藏

de996edf93ef850757c9045eff029154.png

点点赞

dd26a511da09cab30193d6a7f32ad0aa.png

点在看


http://lihuaxi.xjx100.cn/news/255516.html

相关文章

LeetCode实战:求众数

题目英文 Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times. You may assume that the array is non-empty and the majority element always exist in the array. Example 1: Input: […

遇到的浏览器兼容问题及应对方法

前言&#xff1a; 上周天的时候有个学长找我帮忙做三张页面&#xff0c;因为没有数据交换之类的&#xff0c;只是单纯的前端页面&#xff0c;想着好久没做东西&#xff0c; 看书都看烦了&#xff0c;所以就接了也当是练手。之前因为没有系统的看书&#xff0c;所以其实很多问题…

【learning】矩阵树定理

问题描述 给你一个图&#xff08;有向无向都ok&#xff09;&#xff0c;求这个图的生成树个数    一些概念 度数矩阵&#xff1a;\(a[i][i]degree[i]\)&#xff0c;其他等于\(0\) 入度矩阵&#xff1a;\(a[i][i]in\_degree[i]\)&#xff0c;其他等于\(0\) 出度矩阵&#xff1…

硅谷华人码农艰难「求生」:陪马斯克熬夜奋战后光速被裁!

视学算法报道 编辑&#xff1a;David Cris【导读】前一晚还在与马斯克并肩作战&#xff0c;早上起床后公司账号就进不去了&#xff1f;这就是科技寒潮下的「硅谷速度」…根据Layoffs.fyi的统计&#xff0c;今年迄今科技行业累计裁员人数已超10万&#xff0c;其中大部分集中在M…

中国移动数据大赛来了!

第二届中国移动“梧桐杯”大数据应用创新大赛于4月6日正式启动报名啦&#xff01;本届大赛基于中国移动丰富数据资产和核心能力优势&#xff0c;面向广大高校&#xff0c;发掘青年学生优秀大数据应用创意能力&#xff0c;推动大数据产学研用深度融合&#xff0c;打造大数据行业…

WordPress首页调用QQ签名

我的博客&#xff1a;http://Yourtion.TK 看到我的博客的朋友一定注意到我的页面旁边一个QQ签名的实时显示&#xff0c;如下图&#xff1a; 是怎么实现的呢&#xff1f;&#xff1f;下面一步步告诉你。希望对你有帮助。 首先登陆QQ滔滔首页&#xff1a;http://www.taotao.com/并…

如何保证 Controller 的并发安全

欢迎关注方志朋的博客&#xff0c;回复”666“获面试宝典单例模式&#xff08;Singleton&#xff09;是程序设计中一种非常重要的设计模式&#xff0c;设计模式也是Java面试重点考察的一个方面。面试经常会问到的一个问题是&#xff1a;SpringMVC中的Controller是单例还是多例&…

网站速度优化模块HttpCompressionModule

为了优化网站的访问速度&#xff0c;准备采用HttpCompressionModule 6对传输数据进行压缩&#xff0c;下载了HttpCompressionModule 6 , 并按照示例程序中的web.config配置了网站的web.config。<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:offi…