`

如何在Scala中使用条件表达式 .

阅读更多

条件表达式

Scala的if/else语法结构和Java或C++一样。不过,在Scala中if/else表达式有值,这个值就是跟在if或else之后的表达式的值。例如:

if (x > 0) 1 else -1

上述表达式的值是1或−1,具体是哪一个取决于x的值。你可以将if/else表达式的值赋值给变量:

val s = if (x > 0) 1 else -1

这与如下语句的效果一样:

if (x > 0) s = 1 else s = -1

不过,第一种写法更好,因为它可以用来初始化一个val。而在第二种写法当中,s必须是var。

(之前已经提过,Scala中的分号绝大多数情况下不是必需的。)

Java和C++有一个?:操作符用于同样目的。如下表达式

x > 0 ? 1 : -1 // Java或C++

等同于Scala表达式 if (x > 0) 1 else −1。不过,你不能在?:表达式中插入语句。Scala的if/else将在Java和C++中分开的两个语法结构if/else和?:结合在了一起。

在Scala中,每个表达式都有一个类型。举例来说,表达式 if (x > 0) 1 else −1的类型是Int,因为两个分支的类型都是Int。混合类型表达式,比如:

if (x > 0) "positive" else -1

上述表达式的类型是两个分支类型的公共超类型。在本例中,其中一个分支是java.lang.String,而另一个分支是Int。它们的公共超类型叫做Any。(详细内容参见8.11节。)

如果else部分缺失了,比如:

if (x > 0) 1

那么有可能if语句没有输出值。但是在Scala中,每个表达式都应该有某种值。这个问题的解决方案是引入一个Unit类,写做()。不带else的这个if语句等同于

if (x > 0) 1 else ()

你可以把()当做是表示“无有用值”的占位符,将Unit当做Java或C++中的void。(从技术上讲,void没有值但是Unit有一个表示“无值”的值。如果你一定要深究的话,这就好比空的钱包和里面有一张写着“没钱”的无面值钞票的钱包之间的区别。)

说明:Scala没有switch语句,不过它有一个强大得多的模式匹配机制,我们将在第14章中看到。在现阶段,用一系列的if语句就好。

注意:REPL比起编译器来更加“近视”——它在同一时间只能看到一行代码。

举例来说,当你键入如下代码时:

if (x > 0) 1

else if (x == 0) 0 else -1

REPL会执行 if (x > 0) 1,然后显示结果。之后它看到接下来的else关键字就会不知所措。

如果你想在else前换行的话,用花括号:

if (x > 0) { 1

} else if (x == 0) 0 else -1

只有在REPL中才会有这个顾虑。在被编译的程序中,解析器会找到下一行的else。

提示:如果你想在REPL中粘贴成块的代码,而又不想担心REPL的近视问题,可以使用粘贴模式。键入:

:paste

把代码块粘贴进去,然后按下Ctrl+D。这样REPL就会把代码块当做一个整体来分析。

语句终止

在Java和C++中,每个语句都以分号结束。而在Scala中——与JavaScript和其他脚本语言类似——行尾的位置不需要分号。同样,在}、else以及类似的位置也不必写分号,只要能够从上下文明确地判断出这里是语句的终止即可。

不过,如果你想在单行中写下多个语句,就需要将它们以分号隔开。例如:

if (n > 0) { r = r * n; n -= 1 }

我们需要用分号将 r = r * n 和 n -= 1 隔开。由于有},在第二个语句之后并不需要写分号。

如果你在写较长的语句,需要分两行来写的话,就要确保第一行以一个不能用做语句结尾的符号结尾。通常来说一个比较好的选择是操作符:

s = s0 + (v - v0) * t + // +告诉解析器这里不是语句的末尾

0.5 * (a - a0) * t * t

在实际编码时,长表达式通常涉及函数或方法调用,如此一来你并不需要过分担心——在左括号(之后,编译器直到看到匹配的)才会去推断某处是否为语句结尾。

正因如此,Scala程序员们更倾向于使用Kernighan & Ritchie风格的花括号:

if (n > 0) {

r = r * n

n -= 1

}

以{结束的行很清楚地表示了后面还有更多内容。

许多来自Java或C++的程序员一开始并不适应省去分号的做法。如果你倾向于使用分号,用就是了——它们没啥坏处。

块表达式和赋值

在Java或C++中,块语句是一个包含于{ }中的语句序列。每当你需要在逻辑分支或循环中放置多个动作时,你都可以使用块语句。

在Scala中,{ }块包含一系列表达式,其结果也是一个表达式。块中最后一个表达式的值就是块的值。

这个特性对于那种对某个val的初始化需要分多步完成的情况很有用。例如,

val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy) }

{ }块的值取其最后一个表达式,在此处以粗体标出。变量dx和dy仅作为计算所需要的中间值,很干净地对程序其他部分而言不可见了。

在Scala中,赋值动作本身是没有值的——或者,更严格地说,它们的值是Unit类型的。你应该还记得,Unit类型等同于Java和C++中的void,而这个类型只有一个值,写做()。

一个以赋值语句结束的块,比如

{ r = r * n; n -= 1}

的值是Unit类型的。这没有问题,只是当我们定义函数时需要意识到这一点。

由于赋值语句的值是Unit类型的,别把它们串接在一起。

x = y = 1 // 别这样做

y = 1的值是(),你几乎不太可能想把一个Unit类型的值赋值给x。(与此相对应,在Java和C++中,赋值语句的值是被赋的那个值。在这些语言中,将赋值语句串接在一起是有意义的。)

输入和输出

如果要打印一个值,我们用print或println函数。后者在打印完内容后会追加一个换行符。举例来说,

print("Answer: ")

println(42)

与下面的代码输出的内容相同:

println("Answer: " + 42)

另外,还有一个带有C风格格式化字符串的printf函数:

printf("Hello, %s! You are %d years old.\n", "Fred", 42)

你可以用readLine函数从控制台读取一行输入。如果要读取数字、Boolean或者是字符,可以用readInt、readDouble、readByte、readShort、readLong、readFloat、readBoolean或者readChar。与其他方法不同,readLine带一个参数作为提示字符串:

val name = readLine("Your name: ")

print("Your age: ")

val age = readInt()

printf("Hello, %s! Next year, your will be %d.\n", name, age + 1)

 

 

 

本文节选自《快学Scala

电子工业出版社出版

(美)霍斯曼(Horstmann,C.S.)著

高宇翔译

分享到:
评论

相关推荐

    Scala快速从入门到神坑

    4.1 if条件表达式 4.2 while循环 4.3 for循环 4.3.1 实例 4.3.2 for推导式 五、 数据结构 5.1 数组 5.2 列表(List) 5.3 元组(Tuple) 5.4 集(Set) 5.5 映射(Map) 5.6 迭代器(Iterator) 六、类(Class) 6.1 简单的类 ...

    第4讲-Scala编程详解:条件控制与循环.rar

    1. if表达式 2.语句终结符、块表达式 3.输入和输出 4.循环 5.高级for循环

    Scala程序设计(第2版)

    22.1 在Scala代码中使用Java名称 430 22.2 Java泛型与Scala泛型 430 22.3 JavaBean的性质 432 22.4 AnyVal类型与Java原生类型 433 22.5 Java代码中的Scala名称 433 22.6 本章回顾与下一章提要 434 ...

    快学 scala 中文版 带完整目录

    16.5 在属性中使用表达式 264 16.6 特殊节点类型 265 16.7 类XPath表达式 266 16.8 模式匹配 267 16.9 修改元素和属性 268 16.10 XML变换 269 16.11 加载和保存 270 16.12 命名空间 273 练习 275 第17章 ...

    python中Lambda表达式详解

    在这一节里,虽然我们 不打算深入学习这类函数,但是会用几个例子来演示它们是如何用在网 页抓取中的。 Lambda 表达式本质上就是一个函数,可以作为变量传入另一个函数; 也就是说,一个函数不是定义成 f(x, y),...

    Scala—— 2. 流程控制

    条件表达式 val x = 3 val y = if(x > 1) 1 else -1 B.混合类型表达式 支持返回多种类型(前提是在不确定类型的情况下,val y:String或val y:Int这样都不行)。 val y = if(x > 1) 1 else hello val b = if(x < ...

    neodsl:scala中neo4j的DSL

    新DSL 这是用 Scala 编写的用于图形数据库...让您为被序列化为 WHERE 语句的返回节点表达简单的条件(对布尔表达式使用基本的 Scala 语法,使用 Scala 宏实现) 将结果从数据库映射到域类 它没有(还没有!): 不会

    ramen:一个简单而优雅的 Java 和 Scala 规则引擎,旨在易于使用和有趣的工作

    拉面规则使用 MVEL ( ) 表达式语言来定义规则条件和操作。入门以下代码段快速概述了在 Java 代码中定义一些规则的基本用法: Person john = new Person ( " John " , 15 );Person anna = new Person ( " Anna " , ...

    ReadLogic:ReadLogic 是一个用于解析逻辑表达式(ISO Prolog 语法)的小型开源库,用 Scala 编程语言实现

    ReadLogic是一个用于解析逻辑表达式(ISO Prolog 语法)的小型开源库,使用。 执照 根据 Apache 许可,版本 2.0(“许可”)获得许可; 除非遵守许可,否则您不得使用此文件。 您可以从获得许可证的副本。 除非适用...

    smatch:用于Java的Scala样式模式匹配

    它使用声明性API,该API允许面向表达式的编程,通过消除通常用于检查对象的复杂和/或冗长的条件逻辑的代码,从而提供最大的代码清晰度。 这使您可以清楚地指定程序的意图,从而提高可读性和可维护性。 smatch被构建...

    像计算机科学家一样思考Python(第2版).pdf

    从2.3版本开始接触Python,工作中使用Python编写脚本程序,用于快速原型构建以及日志计算等日常作业;业余时,作为一个编程语言爱好者,对D、Kotlin、Lua、Clojure、Scala、Julia、Go等语言均有了解,但至今仍为...

    java8stream源码-java-ast-instrumentation:java-ast-instrumentation

    应用程序的跟踪信息被发送到启动程序,在该程序中使用哈希表来跟踪程序执行不同点的变量、它们的绑定和值。 先决条件 JAVA SDK 11 或更高版本 Scala 2.13 或以上 注意:该项目是在基于 Linux 的操作系统(确切地说是...

    karate-conduitApp

    嵌入式和多行表达式 数据驱动的方案(“方案概述和示例”表) 模糊匹配 回应的断言 使用模式进行模式验证 测试数据生成器(动态值) 读取其他文件 之前和之后的钩子 独立的流道用于并行执行 条件逻辑 类型转换 ...

    nMix:基于混合网,密码安全的投票系统的后端

    软件架构nMix遵循一个最小的设计,由由Git支持的仅附加公告板声明式指定的React式,数据驱动的选举协议布尔表达式条件的最小规则引擎用于多核支持的 (包括 )库这允许通过无状态和幂等受托人进行容错通过Git的哈希...

Global site tag (gtag.js) - Google Analytics