Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

表达式与语句

语句表达式 是大多数编程语言中最小的有用代码片段。

两者之间有基本的区别:语句具有影响,但不产生结果。而表达式总是产生结果。

由于它不产生结果,所以语句必须改变其周围的状态才能有用。另一种表达这个观点的方式是“语句是为了其副作用而调用的”(即它除了产生结果之外的其他操作)。可以这样记忆:

语句改变状态

“表达”的一个定义是“挤压或挤出”,就像“从橙子中挤出果汁”。因此:

表达式表达

也就是说,它产生了一个结果。

在 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() 也会返回 Unitval 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 时发生的。

注意,aresult2 的代码块中被定义。最后一个表达式的结果成为 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
*/

递减操作符也有两个版本:--ii--。在其他表达式中使用递增和递减操作符是不鼓励的,因为它可能产生令人困惑的代码:

// ExpressionsStatements/Confusing.kt

fun main() {
  var i = 1
  println(i++ + ++i)
}

试着猜猜输出会是什么,然后进行验证。

练习和解答可在 www.AtomicKotlin.com 找到。