执行顺序 - Kotlin

Order of execution - Kotlin

我已经尝试调试下一个程序以了解执行顺序,但我仍然对执行顺序感到困惑

fun foo(): String{
    println("Calculating foo...")
    return "foo"
}

fun main(args: Array<String>) {
    println("First ${foo()}, Second ${foo()}!")
}
// Result:
//
// Calculating foo...
// Calculating foo...
// First foo, Second foo!

// I though the execution would show something like this:
//
// First Calculating foo...foo,
// Second Calculating foo...foo!

main不是要执行的初始函数吗? 如果是,那么 println 将是第一句话,因此(对我而言)执行将从左到右开始(我正确吗?),所以...如果是第一个要显示的词是 First ,然后它将被称为 foo() 函数,这将是 return "foo",这将再次外推到字符串 => ${} ...我说得对吗? 如果不是,我误会了什么?

感谢您的澄清。

这里有两个概念:

  1. 字符串插值将使用您的函数的输出来构建输出文本。 foo() 中的 println 调用是 side-effect,不包含在 return 值中。因此,它不会被添加到生成的字符串中。
  2. main函数中的println会收到String插值的结果。文本在传递给 println 之前被完全解释。这就是为什么您按原样看到输出的原因:为了创建最终文本,kt 将首先执行每个字符串表达式,然后构建要显示的整个字符串,最后将准备好的文本传递给 println 函数。

代码执行顺序与自然阅读顺序没有强绑定关系。有运算符优先级的概念,在执行函数时,它的所有参数都必须在传递给它之前进行评估(closures/lambda 除外,但这是一个更复杂的主题)。还有更多的规则。我只能鼓励你参加一般的编程课程来发现所有这些,因为有很多话要说,很难将所有内容都包含在一个 SO 答案中。

Kotlin's String templates 静态解析,并转换为与字符串串联的相应 variable/function 调用。

"test ${foo()} test2"这样的文字在JVM字节码中将被编译为"test " + foo() + "test2"


基本上,你的函数调用,

println("First ${foo()}, Second ${foo()}!")

被砍成这样:

println("First " + foo() + ", Second " + foo() + "!")

这将执行如下:

println(  "First ".plus(foo()).plus(", Second ").plus(foo()).plus("!")  )

所以首先,所有的 foo 调用都是在以上述方式连接所有字符串之后进行的,最终字符串作为参数发送给 println()

你可以这样想

  1. 执行 main() 函数。
  2. 评估 println() 函数的参数。
    • "First ${foo()}, Second ${foo()}!"使用的是字符串插值,所以我们需要先对字符串进行插值。
  3. 首先通过调用 foo()
  4. 进行插值 ${foo()}
  5. 第一个 foo() 打印 "Calculating foo..."
  6. 通过调用 foo()
  7. 插入第二个 ${foo()}
  8. 第一个 foo() 打印 "Calculating foo..."
    • 现在我们有了内插字符串 First foo, Second foo!
  9. 执行println("First foo, Second foo!")