1. Scala 的内建控制结构

Scala 有几个内建的控制结构,包括:

  • if 表达式
  • while 循环和 do-while 循环
  • for 表达式
  • try 表达式
  • match 表达式

Scala 的所有控制结构都返回某种值作为结果,这是函数式编程采取的策略:

程序是被用来计算出某个值,所以程序的各个组成部分也应该计算出某个值。

以上的5个控制结构中,有一个被称之为循环,而不是表达式,因为它不会返回一个有意义的值。

while 和 do-while 的返回值的类型永远都是 Unit,即单元值,写作 ()。Scala 的赋值语句的结果也是 ()。

2. if 表达式

if 表达式的使用方法,大致与 Java 相同。

有一个区别于 Java 的使用方法,就是由于 if 表达式有返回值,所以在某些场景下可以用来赋值:

  def main(args: Array[String]): Unit = {
val fileName = if (args.isEmpty) args(0) else "default"
}

3. while 和 do-while 循环

while 和 do-while 循环的使用方法,也大致与 Java 相同。

但是这里需要注意的是,由于循环的结果永远都是 Unit,所以从函数式编程的角度,不建议使用循环,因为这么做纯粹是为了程序的副作用。

while 循环通常用来更新一个 var 的值,所以两者很多时候都是成对出现。

4. for 表达式

for 表达式主要用于迭代。

4.1 遍历集合

for 表达式最常见的场景就是遍历一个集合(包括 List,Set,Map,Array)

  def main(args: Array[String]): Unit = {
val list = List(1, 2, 3)
for (i <- list) println(i) val map = Map(1 -> "1.1", 2 -> "2.2")
for ((k, v) <- map) println(k + "," + v)
}

4.2 遍历区间

for 表达式还可以用来遍历区间 Range,这是一种对于 Int 类的富包装。

  def main(args: Array[String]): Unit = {
for (i <- 1 to 3) print(i) // 输出123
for (i <- 1 until 3) print(i) // 输出12
}

其中 until 和 to 的区别在于:until 不包含上界,to 包含上界。

也可以使用区间来遍历集合,但这种用法在 Scala 中不推荐:

  def main(args: Array[String]): Unit = {
val list = List(1, 2, 3)
for (i <- 0 until list.length) println(list(i)) // 不推荐
} 

4.3 过滤

遍历集合时,可以给 for 表达式增加 filter,具体的做法是在 for 表达式的圆括号中加一个 if 子句:

  def main(args: Array[String]): Unit = {
val list = List(1, 2, 3)
for (i <- list if i > 1) println(i) // 输出23
}

支持同时使用多个 filter:

  def main(args: Array[String]): Unit = {
val list = List(1, 2, 3)
for (i <- list if i > 1 if i % 2 == 0) println(i) // 输出2
}

4.4 嵌套迭代

for 表达式内部可以写多个 <- 子句,表示嵌套迭代。

这里写一个典型的嵌套迭代:冒泡排序

  def main(args: Array[String]): Unit = {
val array = Array(4, 2, 5, 1, 3)
bubble(array)
for (i <- array) print(i) } def bubble(array: Array[Int]) = {
for (i <- 0 until array.length - 1; // 注意,嵌套迭代之间的分号是不能省略的
j <- 0 until array.length - i - 1 if array(j) > array(j + 1)) swap(array, j, j + 1)
} def swap(array: Array[Int], i: Int, j: Int) = {
val temp = array(i)
array(i) = array(j)
array(j) = temp
}

需要注意的是:

  • 如果 for 表达式使用圆括号,嵌套迭代之间的分号是不能省略的。
  • 如果 for 表达式使用花括号,嵌套迭代之间的分号可以省略。
  • 外循环与内循环之间除了使用过滤器,或者中途变量绑定,不能增加其他操作。

所谓中途变量绑定,就是用 = 在 for 表达式内部进行临时的变量绑定(使用这个技巧可以在循环之间增加额外的操作)

  def bubble(array: Array[Int]) = {
for {i <- 0 until array.length - 1
// println() 编译出错
a = println() // 编译成功
j <- 0 until array.length - i - 1 if array(j) > array(j + 1)} swap(array, j, j + 1)
}

4.5 yield

for 表达式在每次迭代中,都可以生成一个可以被记住的值,具体的做法实在 for 表达式的代码体之前使用 yield 关键字。

交出的值,被统一存储在一个集合里面,这个集合的类型取决于迭代子句中处理的集合种类:

  def main(args: Array[String]): Unit = {
val array = Array(1, 2, 3)
val a = for (i <- array if i % 2 == 0) yield i // a是Array val list = List(1, 2, 3)
val b = for (i <- array if i % 2 == 0) yield i // b是List
}

5. try 表达式

try 表达式用来处理异常情况,与 Java 基本相同,是 try-catch-finally 结构。

try 表达式在 catch 模块与 Java 的语法不相同:

  def myDivide(a: Int, b: Int): Int = {
try {
if (a < 0 || b < 0) throw new Exception else a / b
} catch {
case ex: ArithmeticException => -1
case ex: Exception => -2 // 这行注释掉编译也不会出现问题
} finally {
println("Go to finally")
    -3
}
}

try-catch-finally 结构也会交出一个值,但是 finally 中的语句虽然始终被执行,但是却和交出值没有关系。

例如:

  def main(args: Array[String]): Unit = {
println(myDivide(2, -1)) // 结果是 -2
}

因此我们可以做一个初步的总结:

  • try 表达式用于异常捕获。
  • Scala 的受检异常(checked exception),从编译的角度上不强制要求我们 catch,这点和 Java 不一样。
  • catch 子句遵循模式匹配用法。
  • try 表达式可以交出一个值。
  • finally 子句始终会被执行,但是不参与交出值,所以一般用来做资源回收之类的工作。

6. match 表达式

Scala 的 match 表达式,从控制结构的角度上讲,对应的是 Java 的 switch-case 结构。

当然 match 表达式的作用不仅限于此,它属于 Scala 的模式匹配的其中一种用法,此处不展开。

  def main(args: Array[String]): Unit = {
val str = if (args.length > 0) args(0) else "default"
val firstArg = str match {
case "1" => "one"
case "default" => "zero"
case _ => "nothing" // 和 Java 中的 default 关键字起相同的作用
}
println(firstArg)
}

Scala 的 match 表达式和 Java 的 switch-case 结构有三处区别:

  • Scala 中的任何常量、字符串都可以作为 match 表达式匹配的样例。
  • Scala 的 match 表达式每个可选象后面不需要有 break。
  • Scala 的 match 表达式有返回值。

7. break & continue

Scala 语言里,没有 break 和 continue 关键字。

所以如果需要类似的语义,在使用 while 或 do-while 循环,或是 for 表达式的时候,需要对程序做一定的修改。

最简单的解决方案是:

  • 用 if 换掉每一个 continue。
  • 用布尔值取代 break。

Scala 基础(6)—— 控制结构的更多相关文章

  1. 【Scala学习之一】 Scala基础语法

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

  2. Scala学习(一)--Scala基础学习

    Scala基础学习 摘要: 在篇主要内容:如何把Scala当做工业级的便携计算器使用,如何用Scala处理数字以及其他算术操作.在这个过程中,我们将介绍一系列重要的Scala概念和惯用法.同时你还将学 ...

  3. Scala基础(1)

    Scala基础语法 声明与定义: val,常量声明                       val  x:T(把x声明成一个类型为T的常量)  x是变量的名字,T是变量的类型          v ...

  4. scala 基础知识总结

    在最开始处引入 log 相关的 包 import org.apache.log4j.{Logger,Level} 在需要屏蔽日志输出的地方加上这两行代码 // 屏蔽不必要的日志显示在终端上 Logge ...

  5. Scala具体解释---------控制结构和函数

    条件表达式: Scala的if else语法结构和Java的一样.只是,Scala的if else表达式有值.这个值就是跟在if或者else后面的表达式的值. 比如: if(x>0) 0 els ...

  6. 1.scala基础语法总结

    Scala基础语法总结:Scala 与 Java 的最大区别是:Scala 语句末尾的分号 ; 是可选的.如果一行里写多个语句那么分号是需要的 val s = "菜鸟教程"; pr ...

  7. Scala 基础(8)—— 占位符_和部分应用函数

    1. 占位符 _ 针对 Scala 基础(7)—— 函数字面量和一等函数 中最后提到的,关于 filter 函数字面量的精简写法,可以使用占位符 _ 来代替. 占位符_,用来表示一个或者多个参数.(这 ...

  8. Scala 基础(7)—— 函数字面量和一等函数

    1. 函数字面量 在 Scala 基础(3)—— 基础类型和基础操作 中提到了函数字面量,这里具体解释函数字面量的语法. 下面展示一个具体的函数字面量,它由三部分组成: (x: Int, y: Int ...

  9. Scala 基础(5)—— 构建函数式对象

    有了 Scala 基础(4)—— 类和对象 的前提,现在就可以来构建一个基于 Scala 的函数式对象. 下面开始构造一个有理数对象 Rational. 1. 主构造方法和辅助构造方法 对于每一个类的 ...

随机推荐

  1. javascript入门笔记8-window对象

    History 对象 history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能. 注意:从窗口被打开的那一刻开始记录,每个浏览器窗口.每个标签页乃至每个框架,都 ...

  2. c++谭浩强教材教学练习例题1.2 求两数之和 为什么sum=a+b;sum的值为65538

    第一章 #include <iostream>using namespace std; int main(){ int a,b,sum; sum=a+b; cin>>a> ...

  3. JS常见内置对象和方法

    JS中常用的内置对象:Array对象.Date对象.正则表达式对象.string对象.Global对象  Array对象中常用方法: concat() 表示把几个数组合并成一个数组join()   设 ...

  4. 洛谷题解:P1209 【[USACO1.3]修理牛棚 Barn Repair】

    原题传送门:https://www.luogu.org/problemnew/show/P1209 首先,这是一道贪心题.  我们先来分析它的贪心策略.  例如,样例:  4 50 18  3 4 6 ...

  5. 内置函数系列之 map

    map(映射函数)语法: map(函数,可迭代对象) 可以对可迭代对象中的每一个元素,分别执行函数里的操作 # 1.计算每个元素的平方 lst = [1,2,3,4,5] lst_new = map( ...

  6. 关于Mysql唯一索引的操作方法(添加删除)

    首先我们查看一下News数据表的索引信息      使用命令 show index from ‘数据表名称’; 目前数据表中仅有一个主键索引 继续,我们给news表添加两个唯一索引(两种方法) 方法一 ...

  7. 阿里云Linux服务器,挂载硬盘并将系统盘数据迁移到数据盘

    因为之前用宝塔上线,宝塔只挂载了系统盘50G,打开阿里云云盘列表发现系统盘无法直接升级,故另买一块数据盘挂载到Linux服务器下,下面根据网上教程再结合我实际情况讲解一下实际操作,其实非常easy l ...

  8. Python学习笔记:Matplotlib(数据可视化)

    Matplotlib是一个可以将数据绘制为图形表示的Python三方库,包括线性图(折线图,函数图).柱形图.饼图等基础而直观的图形,在平常的开发当中需要绘图时就非常有用了. 安装:pip insta ...

  9. python系列3之内置函数和文件操作

    目录 自定义函数 内置函数 文件的操作 练习题 一. 自定义函数 1. 函数的创建 函数的创建 1.def关键字 2.函数名+() 3.冒号 4.缩进 5. return返回值,可以不写,默认的返回值 ...

  10. 第二章习题 C++

    1.编写一个程序,显示您的姓名和地址. #include<iostream> using namespace std; int main() { ]; cout << &quo ...