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

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

640.png

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 = 0
scala> var i = 0
var i: Int = 0
scala> 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 = 1
scala> 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中都有所体现,且均具有一定特色,灵活掌握还是比较方便的。


640.png






目录
相关文章
|
机器学习/深度学习 算法 决策智能
智能解决装箱问题:使用优化算法实现高效包装
装箱问题(Bin Packing Problem)是组合优化领域中的一个经典问题,主要涉及如何将一系列对象高效地装入有限数量的容器(或“箱”)中,同时满足特定的约束条件。这个问题的目标是最小化所需使用的箱子数量或者最大化箱子的装载效率,以减少空间或资源的浪费。
|
JavaScript
vue关于通过下标更改数组的理解
vue关于通过下标更改数组的理解
|
数据库连接 数据库 Android开发
Android -- Room简化数据库设置图书案例
Android -- Room简化数据库设置图书案例
244 0
|
人工智能 API 开发者
阿里CEO吴泳铭-2024互联网大会发言:AI的最大价值是推动生产力变革
11月21日,2024年世界互联网大会“互联网企业家论坛”在乌镇召开。阿里巴巴CEO吴泳铭表示,AI的最大价值在于推动各行各业的生产力变革,而非仅限于开发超级APP。他强调,发展AI需建设繁荣的技术、产品和市场生态。目前,30多万家企业已接入阿里“通义”大模型,应用于代码开发、药物研发等场景。阿里巴巴坚持开源路线,全球开发者基于“通义千问”开发的衍生模型已突破7.8万个。吴泳铭认为,AI的发展需要行业共同努力,建设繁荣生态以实现高质量持续发展。
|
Web App开发 XML 前端开发
CSS基础-超详解 (1)
CSS基础-超详解 (1)
124 0
|
机器学习/深度学习 编解码 PyTorch
手机图像去噪
NAFNet是一个没有激活函数的神经网络。目前,在图像修复领域有多种类型的网络结构。
|
Linux Windows
一秒学会文件内容浏览,cut命令使用,uniq命令使用,sort命令,tr
一、文件内容浏览 a.cat查看/etc/passwd文件内容,且输出时带行号
355 0
|
存储 索引 Python
Python刷题系列(5)_set集合(上)
set 是一个不允许内容重复的组合,而且set里的内容位置是无序的,所以不能用索引列出。可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
Python刷题系列(5)_set集合(上)
|
机器学习/深度学习 JavaScript 前端开发
前端培训-中级阶段(45)- Node10.x环境搭建,NPM包管理器
前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。 上节课我们了解到了一个可以在本地执行 js 的 javascript 执行环境:NodeJS。今天我们来安装 NodeJS、环境配置、NPM 使用、版本管理。 推荐使用 node 10.x 版本(2018年,最新是 10.22.1),下文我们基于 v10.16.0 版本。
363 0
前端培训-中级阶段(45)- Node10.x环境搭建,NPM包管理器
|
人工智能 搜索推荐 大数据
上海市经信委将“远程办公”列入在线经济发展重点
上海市经信委将“远程办公”列入在线经济发展重点,泛微智能化、平台化、全程电子化的OA系统移动办公平台随需而变,帮助各个行业组织搭建符合业务需求的个性化服务场景,让众多组织实现远程协作、高效办公…