【问题标题】:How do the Swift REPL and the swiftc compiler interpret the language differently?Swift REPL 和 swiftc 编译器如何以不同的方式解释语言?
【发布时间】:2020-05-02 23:29:09
【问题描述】:

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

在我的一个实验中,我发现了一个显着的差异,即“让”的工作原理。

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

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

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

【问题讨论】:

标签: swift read-eval-print-loop


【解决方案1】:

在 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 也具有此功能,例如 C# 的 csharppad.com、Haskell 的 ghcipython,仅举几例。所以这实际上只是你在实现 REPL 时所做的一件普通的事情,而不是 Swift 的特殊之处。

实际上,您可以通过在一个函数中编写这两行代码来重现 REPL 中的 swiftc 行为,因为现在这两行代码在同一个提交中,不会相互覆盖。

【讨论】:

  • “在 REPL 环境中,您希望能够重新声明变量,对吗?”谢谢你的回答,我明白你的意思。我希望 REPL 在语法上与编译器相同。例如,由于这种差异,我无法有意义地尝试隐式展开的选项。使用一种故意清除/取消设置的形式来完成您的建议,会更有意义。有什么建议可以列出/记录此和其他 REPL/swiftc 差异吗?
  • This link 在 Martin R 链接的帖子中。看看那里。这算作“文档”吗? @P2000
  • @P2000 我不明白为什么此功能会阻止您尝试隐式展开的选项。你能详细说明一下吗?
  • 好的,你是对的。经过一番深思熟虑(我是一位经验丰富的编码员,但对 Swift 不熟悉),我会说这确实是同一个问题的重复:让可以重新出租。我的意思是let x: Int! = 3 以后可以变成let x: Int! = int 并使用 x 在后续代码中公开 nil。在微观的“修补程序”代码中,这真的无关紧要。我担心 REPL 被用于 hash-bang 脚本,但事实证明并非如此。您与 Martin R 的链接非常完美:“(...) REPL 违反了正常的编码规则”。用户小心!
  • 您介意将链接添加到您的答案中吗?我会将其标记为已回答。
猜你喜欢
  • 1970-01-01
  • 2021-01-15
  • 2010-09-06
  • 2016-11-24
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 2011-07-23
  • 1970-01-01
相关资源
最近更新 更多