Swift REPL 和 swiftc 编译器如何以不同方式解释语言?

How do the Swift REPL and the swiftc compiler interpret the language differently?

Swift 有一个编译器 (swiftc) 和一个 REPL。我喜欢使用 REPL 来学习和玩弄语言结构。

在我的一个实验中,我发现了一个显着差异 w.r.t "let" 的工作原理。

如我所料,以下内容在 swiftc 中是不允许的,但 REPL 允许。

let x = 10
let x = 20 // ok in REPL

现在我想知道还有哪些其他差异。它们在任何地方都有记录吗?

在 REPL 环境中,您希望能够重新声明变量,对吗?否则,当你继续使用 REPL,并声明越来越多的变量、let 常量、函数、类,无论如何,你将 运行 没有名字可以使用!

例如,假设您想尝试字符串插值:

let x = 10
print("x is \(x)!")

过了一会儿,您了解了字符串连接,您也想尝试一下。此时,您希望能够重新声明一个 let 常量 x,对吗?

let x = "A"
let y = "B"
print(x + y)

你可能会争辩说你可以使用 ab,但随着时间的推移,你会慢慢地 运行 出名字。 REPL就是这样设计的,这样你就不用经常重启REPL了。

因此,每次您提交内容时,之前在提交中声明的符号都会被覆盖。这已记录在案 here

swiftc 有一个完全不同的用例——你通常用它来编译更大的程序,而不仅仅是几行代码。在这些情况下,全局作用域的符号会少很多,并且重新声明变量实际上并不实用,因为代码执行从上到下不是线性的。也可能有多个文件相互交谈。你如何弄清楚什么重新声明了什么?在 REPL 以外的任何地方执行此操作都没有意义。

其他 REPL 也有此功能,例如 csharppad.com 用于 C#,ghci 用于 Haskell,以及 python,仅举几例。所以这真的只是你在实现 REPL 时做的一件普通事情,而不是 Swift.

的特殊事情

事实上,您可以通过将这两行写在一个函数中来在 REPL 中重现 swiftc 行为,因为现在这两行在同一个提交中,并且不会相互覆盖。