就是个控制结构,Scala 能有什么新花样呢?
作者 | 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中都有所体现,且均具有一定特色,灵活掌握还是比较方便的。
往
期
回
顾
资讯
Meta开发AI语音助手,助力元宇宙
技术
霸占CSDN榜一的20个Python用例
技术
20个Pandas数据实战案例,干货多
资讯
安全隐患:神经网络可以隐藏恶意软件
分享
点收藏
点点赞
点在看
相关文章:

快速开发一个PHP扩展
快速开发一个PHP扩展 作者:heiyeluren时间:2008-12-5博客:http://blog.csdn.net/heiyeshuwu 本文通过非常快速的方式讲解了如何制作一个PHP 5.2 环境的扩展(PHP Extension),希望能够在图文的方式下让想快速…

oracle11g的安装
目录层次:linux->oracle软件->dbca数据库安装过程:虚拟机->linux->VMtools->拷贝数据库软件->创建一个目录mkdir->创建组.用户->修改根目录->设置参数->解压 >安装->oracle完成参考:安装oracle软件linu…

python 100例(10)
2019独角兽企业重金招聘Python工程师标准>>> 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多…

cocos2dx-3.9 集成admob
Part 1: 安装GoogleMobileAds framework (即admob) 1. 安装Cocoapods,否则解决依赖关系和配置真的会把人不累死也得烦死 sudo gem install cocoapods 国内用户安装过程中可能遇到SSL连接出错的问题,请参考 Cocoapod安装过程中的幺…

用C语言扩展PHP功能
用C语言扩展PHP功能建议读者群:熟悉c,linux,php PHP经过最近几年的发展已经非常的流行,而且PHP也提供了各种各样非常丰富的函数。但有时候我们还是需要来扩展PHP。比如:我们自己开发了一个数据库系统,而且有自己的库函数来操作数…

手把手快速实现 Resnet 残差模型实战
作者 | 李秋键 出品 | AI科技大本营(ID:rgznai100) 引言:随着深度学习的发展,网络模型的深度也随之越来越深,但随着网络模型深度的加深,往往会曾在这随着模型深度的加大,模型准确率反而下降的问…

JHipster开发环境安装
这里采用官方推荐的Yarn安装方法,默认操作系统为CentOS 7.4。 1 安装JDK 推荐版本:OpenJDK 1.8.0-64bit。 完整安装说明,请参考这里 2 安装Nodejs 推荐版本: v8.11.3 完整安装说明,请参考这里 3 安装Yarn 推荐版本&…

用C语言写PHP扩展
用C语言写PHP扩展 1:预定义 在home目录,也可以其他任意目录,写一个文件,例如caleng_module.def 内容是你希望定义的函数名以及参数: int a(int x,int y)string b(string str,int n) 2:到php源码目录的ext目…

Pandas 数据挖掘与分析时的常用方法
今天我们来讲一下用Pandas模块对数据集进行分析的时候,一些经常会用到的配置,通过这些配置的帮助,我们可以更加有效地来分析和挖掘出有价值的数据。数据集的准备这次我们需要用到的数据集是广为人所知的泰坦尼克号的乘客数据,我们…

MySQL基本概念
1. 分清几个概念:数据库,数据库对象和数据; 数据库分为:系统数据库和用户数据库; 系统数据库 是安装完MySQL服务器后自带的数据库,会记录一些必要的信息,用户不能直接修改这些系统数据库。转载…

SpringMvc+ajax实现文件跨域上传
最近开始学习SpringMVC框架,在学习数据绑定的时候,发现可以使用RequestParam注解绑定请求数据,实现了文件上传。但是如果一个项目是前后端分离的,前端系统向后端服务上传文件该怎么解决了? 首先考虑前端用哪一种方式进…

使用Nmap获取目标服务器开放的服务以及操作系统信息
http://nmap.org/download.html 1.下载安装rpm -vhU http://nmap.org/dist/nmap-5.61TEST5-1.i386.rpmrpm -vhU http://nmap.org/dist/zenmap-5.61TEST5-1.noarch.rpmrpm -vhU http://nmap.org/dist/ncat-5.61TEST5-1.i386.rpmrpm -vhU http://nmap.org/dist/nping-0.5.61TEST5…

Pandas 数据类型概述与转换实战
作者 | 周萝卜 来源 | 萝卜大杂烩 在进行数据分析时,确保使用正确的数据类型是很重要的,否则我们可能会得到意想不到的结果或甚至是错误结果。对于 pandas 来说,它会在许多情况下自动推断出数据类型 尽管 pandas 已经自我推断的很好了&#x…

7.10 数据注解特性--NotMapped
NotMapped特性可以应用到领域类的属性中,Code-First默认的约定,是为所有带有get,和set属性选择器的属性创建数据列。。 NotManpped特性打破了这个约定,你可以使用NotMapped特性到某个属性上面,然后Code-First就不会为这个属性就不…

Condition
2019独角兽企业重金招聘Python工程师标准>>> 1、Condition的简介 线程通信中的互斥除了用synchronized、Object类的wait()和notify()/notifyAll()方式实现外,方法JDK1.5中提供的Condition配套Lock可以实现相同的功能。Condition中的await()和signal()/si…

使用who.is查域名DNS信息以及用sameip.org查其他网站
www.who.is网站可以查域名信息,非常好用:例如查 hack-test.com然后我们可以找找同个IP上的其他站点(旁站:sameip.org)参考: 黑客是怎么攻击一个网站的?

基于 OpenCV 的人脸追踪
作者 | 努比 来源 | 小白学视觉 在Raspberry上启动项目很简单,所以让我们开始吧。 01. 产品清单 Raspberry Pi 4 Model B — 4GB 适用于Raspberry Pi的Pan-Tilt HAT Pi Camera v2 8MP 微型SD卡 迷你HDMI电缆 Raspberry Pi摄像头电缆—尺寸:457mm x …

-bash: /bin/rm: Argument list too long的解决办法
-bash: /bin/rm: Argument list too long的解决办法 当目录下文件太多时,用rm删除文件会报错: -bash: /bin/rm: Argument list too long 提示文件数目太多。 解决的办法是使用如下命令: ls | xargs -n 10 rm -fr ls 输出所有的文件名(用…

React使用ES6语法重构组件代码
首次使用react,要注意react不同版本库,是ES5还是ES6的写法,如何做到统一。下面对于ES6语法重构组件的代码如下:(1)原始代码: <script type"text/babel">var destinationdocumen…

PHP哈希表碰撞攻击原理
哈希表碰撞攻击(Hashtable collisions as DOS attack)的话题不断被提起,各种语言纷纷中招。本文结合PHP内核源码,聊一聊这种攻击的原理及实现。 哈希表碰撞攻击的基本原理 哈希表是一种查找效率极高的数据结构,很多语言…

Java8(jdk1.8)中文档注释处理工具javadoc的环境参量配置及使用方法
Java8(jdk1.8)中文档注释处理工具javadoc的环境参量配置及使用方法Java语言提供了一种功能强大的注释形式:文档注释。如果编写Java源代码时添加了合适的文档注释,然后通过JDK提供的javadoc工具可以直接将源代码里的文档注释提取成一份系统的API文档。jav…

如何读取Excel表格中不同sheet表的同一位置单元格数据,并绘制条形图呢?
作者 | 黄伟呢来源 | 数据分析与统计学之美今天,有位朋友在群里面咨询了一个问题:如何读取Excel表格中"不同sheet表"的同一位置单元格数据,并绘制条形图呢?有人提议用vba,但是不得不说,没有学过v…

vue-router学习笔记
配置路由模式 const routernew VueRouter({routes }) hash模式(默认):通过url的hash来模拟一个完整的url,于是当url改变时,页面不会重新加载。history模式:通过history完成url跳转而不需要重新加载页面。注意:为了防止404错误&…

PHP防止注入攻击
注入攻击不多说了PHP addslashes() 函数--单撇号加斜线转义PHP String 函数定义和用法addslashes() 函数在指定的预定义字符前添加反斜杠。这些预定义字符是:单引号 ()双引号 (")反斜杠 (\)NULL语法addslashes(string)参数描述string必需。规定要检查的字符串。…

首届腾讯数字安全创新大赛在京启动,挖掘新锐力量推动产业创新
3月10日,首届腾讯数字安全创新大赛在京正式启动。本次大赛由腾讯安全和中国产业互联网发展联盟联合主办,腾讯安全、KEEN、元起资本、赛博英杰、数世咨询等多家企业联合发起,中国产业互联网发展联盟安全专委会承办。 大赛旨在寻找网络安全新力…

oracle数据库无监听程序
在电脑---服务---启动oracle tns 如果还是出现错误的话,找到Net Manager,将网络的ip监听删除,将本机的主机名配好,即可打开tns服务 转载于:https://www.cnblogs.com/jiangsheng3/p/5025201.html

个人开发者即时到账收款方案 BufPay.com
BufPay 个人即时到账支付平台前言 作为独立开发者,一般只有一个人独立奋战,做出了产品需要收款是非常麻烦的,接入支付宝微信支付都需要公司公户,而注册公司、开公户等一系列操作非常麻烦,成本也很高一年也要 1w 左右。…

用 Python 制作数据大屏,超简单
作者 | 俊欣来源 | 关于数据分析与可视化今天我们用Streamlit模块来制作一个数据面板,将数据更加直观地呈现给别人观看,整个页面大致如下图所示:制作工具栏在页面的左侧是一个工具栏,工具栏中有多个按钮,分别是“About…

Oracle 12C -- 清空audit记录
1.使用job清空 SQL> dbms_audit_mgmt.create_purge_job(audit_trail_type> DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,audit_trail_purge_interval>12,audit_trail_purge_name>audit_trail_pj,use_last_arch_timestamp>TRUE,container>dbms_audit_mgm…

魔法引用函数magic_quotes_gpc和magic_quotes_runtime的区别和用法
PHP提供两个方便我们引用数据的魔法引用函数magic_quotes_gpc和magic_quotes_runtime, 这两个函数如果在php.ini设置为ON的时候,就会为我们引用的数据碰到单引号和双引号"是自动加上反斜线,帮我们自动转译符号,确保数据操作的…