表达式与语句
语句 和 表达式 是大多数编程语言中最小的有用代码片段。
两者之间有基本的区别:语句具有影响,但不产生结果。而表达式总是产生结果。
由于它不产生结果,所以语句必须改变其周围的状态才能有用。另一种表达这个观点的方式是“语句是为了其副作用而调用的”(即它除了产生结果之外的其他操作)。可以这样记忆:
语句改变状态。
“表达”的一个定义是“挤压或挤出”,就像“从橙子中挤出果汁”。因此:
表达式表达。
也就是说,它产生了一个结果。
在 Kotlin 中,for
循环是一个语句。你不能将它赋值,因为它没有结果:
// ExpressionsStatements/ForIsAStatement.kt
fun main() {
// 不能这样做:
// val f = for(i in 1..10) {}
// 编译器错误信息:
// for is not an expression, and
// only expressions are allowed here
}
for
循环用于其副作用。
表达式产生一个值,可以赋值或作为另一个表达式的一部分使用,而语句始终是顶级元素。
每个函数调用都是一个表达式。即使函数返回 Unit
,并且仅用于其副作用,结果仍然可以被赋值:
// ExpressionsStatements/UnitReturnType.kt
fun unitFun() = Unit
fun main() {
println(unitFun())
val u1: Unit = println(42)
println(u1)
val u2 = println(0) // 类型推断
println(u2)
}
/* 输出:
kotlin.Unit
42
kotlin.Unit
0
kotlin.Unit
*/
Unit
类型包含一个称为 Unit
的单一值,你可以直接返回,就像在 unitFun()
中看到的那样。调用 println()
也会返回 Unit
。val u1
捕获了 println()
的返回值,并明确声明为 Unit
,而 u2
使用了类型推断。
if
创建一个表达式,因此可以将其结果赋值:
// ExpressionsStatements/AssigningAnIf.kt
fun main() {
val result1 = if (11 > 42) 9 else 5
val result2 = if (1 < 2) {
val a = 11
a + 42
} else 42
val result3 =
if ('x' < 'y')
println("x < y")
else
println("x > y")
println(result1)
println(result2)
println(result3)
}
/* 输出:
x < y
5
53
kotlin.Unit
*/
第一行输出是 x < y
,即使 result3
直到 main()
结尾才被显示出来。这是因为评估 result3
调用了 println()
,而这个评估是在定义 result3
时发生的。
注意,a
在 result2
的代码块中被定义。最后一个表达式的结果成为 if
表达式的结果;在这里,它是 11 和 42 的和。但是 a
呢?一旦离开代码块(移到花括号外部),你就无法访问 a
。它是临时的,一旦退出该块的作用域,就会被丢弃。
递增操作符 i++
也是一个表达式,尽管看起来像是一个语句。Kotlin 遵循 C 类似语言使用的方法,并提供了两个版本的递增和递减操作符,具有稍微不同的语义。前缀操作符出现在操作数之前,就像 ++i
,并在递增发生后返回值。你可以将其理解为“首先执行递增,然后返回结果值”。后缀操作符放在操作数之后,就像 i++
,并在递增发生前返回 i
的值。你可以将其理解为“首先产生结果,然后执行递增”。
// ExpressionsStatements/PostfixVsPrefix.kt
fun main() {
var i = 10
println(i++)
println(i)
var j = 20
println(++j)
println(j)
}
/* 输出:
10
11
21
21
*/
递减操作符也有两个版本:--i
和 i--
。在其他表达式中使用递增和递减操作符是不鼓励的,因为它可能产生令人困惑的代码:
// ExpressionsStatements/Confusing.kt
fun main() {
var i = 1
println(i++ + ++i)
}
试着猜猜输出会是什么,然后进行验证。
练习和解答可在 www.AtomicKotlin.com 找到。