【问题标题】:What features of interpreted languages can a compiled one not have?编译型语言没有哪些解释型语言的特性?
【发布时间】:2010-03-26 00:23:47
【问题描述】:

解释型语言通常更高级,因此具有动态类型(包括动态创建新变量而无需声明)、臭名昭著的eval 以及许多其他使程序员的生活更轻松的特性 - 但为什么不能编译语言也有这些?

我不是指像 Java 这样在 VM 上运行的语言,而是那些像 C(++) 这样编译成二进制的语言。

我现在不打算列出清单,但是如果您要问我指的是哪些功能,请查看 PHP、Python、Ruby 等必须提供的功能。

  • 解释语言的哪些共同特性不能/不/不存在于编译语言中?为什么?

【问题讨论】:

  • 这应该是社区维基,因为它没有明确的答案(我什至不确定它不会被关闭)。请按“编辑”并选中“社区维基”框。
  • 另外,我不认为 Java 和 C++ 之间的区别值得讨论。
  • 看看stackoverflow.com/questions/2147662 了解一些类似的想法!
  • 答案是否定的。编译器实现可以做任何解释器实现可以做的事情。

标签: language-agnostic programming-languages


【解决方案1】:

无论源代码是编译成本机二进制文件、某种中间语言(Java 字节码/IL)还是解释性的,都绝对没有语言的特征。这只是实施的问题。

实际上,您可以同时拥有同一种语言的编译器和解释器,例如

  • Haskell:GHC GHCI
  • C: gcc ch
  • VB6:VS IDE VB6 编译器

某些语言特性,如 eval 或动态类型,可能表明所谓的“动态语言”和静态语言之间存在区别,但 如何 这绝不是主要问题。

【讨论】:

  • +1。当您运行已编译的 Java 时,您实际上是在解释 Java 字节码。除了 Ruby 是人类可读的而 Java 字节码不是这一事实之外,我没有看到很多差异。那不相关。如果您考虑一下,我们可以忽略编译和解释之间的“人为”区别,让这个问题没有实际意义,而是考虑动态/静态的划分。
  • @Martinho:没错。甚至可以调用包含编译器的源代码的独立解释器;)
  • 我想知道是否有可能创建一种无法编译的编程语言。
  • 此外,在底部,机器代码只是由处理器解释。
【解决方案2】:

最初,解释语言的最大好处之一是调试。这样,在查找程序无法运行的原因时,您可以获得非常准确和详细的信息。然而,大多数编译器已经变得足够先进,这已经不是什么大不了的事情了。

另一个主要好处(无论如何,在我看来)是,使用解释型语言,您不必等待永恒的项目编译来测试它。

【讨论】:

  • 没有解决问题。
【解决方案3】:

例如,您无法合理地执行eval,原因我认为很明显:您将如何实现它?使运行时包含编译器的完整副本?每次你想要评估一个字符串时(记住每次它都可能不同!)你会把字符串保存到一个文件中,在它上面运行编译器来创建一个 DLL/shared-lib,然后加载那个 DLL/ shared-lib 并调用您的代码?你不明白为什么这可能有点不切实际? ;)

你可以在动态语言中找到这种你不能用静态代码做的事情,除非基本上运行一个解释器,实际上是在幕后。

【讨论】:

  • 我认为你可以进行评估。你已经说过了:使运行时包含编译器的完整副本。这就是解释语言的工作方式,对吧?调用 eval 就是调用解释器。因此,在编译语言中,它应该只是调用编译器。在 .NET 中,您可以直接发出 IL(某种程序集/字节码),而必须“将字符串保存到文件,......加载 DLL”。这并不少见。尽管没有多少人使用与“eval”完全一样的东西,但这并不是那么不切实际。
  • 一个真实的例子:boo 被编译并且有一个解释器。我认为在解释器的内部某处有一个 eval 。还有,达里奥说的。
  • 我看到了 C# 的 REPL 行为演示。所以,eval 可以用编译语言来完成。
  • @John Fisher:这可能是 Anders Hejlsberg 在 PDC'08 (channel9.msdn.com/pdc2008/TL16) 上的演讲。当时他正在使用 C#“超越 4.0”语言的原型。
  • 现实世界的例子:Common Lisp。编译好的实现。
【解决方案4】:

从 Dario 继续 - 我认为您真的在问为什么编译的程序不能在运行时评估语句(例如 eval)。以下是我能想到的一些原因:

  • 完整的编译器必须与程序一起分发(或成为程序的一部分)
  • 要让 eval 函数在使用它的环境中访问类型信息和符号(例如变量名和函数名),原始程序必须使用可访问的符号进行编译(编译语言通常在编译时间)。

编辑:如前所述,这些原因都没有使语言/编译器无法在运行时评估代码,但它们绝对是在开发编译器或设计语言时需要考虑的事情。

【讨论】:

  • Common Lisp 在运行时有eval,并编译了工业级实现。
  • 我并不是说编译的程序不可能有 eval,我只是给出许多语言没有 eval 的一些原因。我会更新我的答案以明确这一点。
  • 编译器可以与运行时一起分发,就像解释器不是解释程序的一部分一样。此外,.NET 和 Java 等现代平台在编译单元(.NET 中的程序集,Java 中的 JAR)中携带类型信息作为元数据。只有局部变量名称被剥离,因为即使局部变量本身也可以通过优化完全删除。
  • 是的 - 关于eval,请参阅stackoverflow.com/questions/2261628/…:可能很有趣
【解决方案5】:

也许问题不在于解释/编译的语言(无论如何编译都是模棱两可的),而是关于带有/不带有自己的编译器的语言?例如,我们说过 C++ 可以使用在应用程序中浮动的方便编译器进行 eval,并且反射在某些方面可能是相似的。

【讨论】:

  • 有一些 C 编译器库正是为此目的而设计的:因此您可以将 C 编译器嵌入到您的应用程序中,以便使用 C 编写脚本。libtcc 就是这样一个例子。
猜你喜欢
  • 2011-03-16
  • 2011-01-20
  • 1970-01-01
  • 2023-04-09
  • 2010-12-13
  • 1970-01-01
  • 2016-11-24
  • 2011-02-09
  • 1970-01-01
相关资源
最近更新 更多