What features of interpreted languages can a compiled one not have?
解释语言通常更高级,因此具有动态类型(包括在没有声明的情况下动态创建新变量)、臭名昭著的eval和许多其他使程序员的生活更容易的功能,但为什么编译语言也不能拥有这些功能呢?
我不是指像Java那样运行在VM上的语言,而是指像C(++)那样编译成二进制的语言。
我现在不打算列出一个列表,但是如果你想问我的意思是什么功能,请看看PHP、Python、Ruby等必须提供什么。
- 在编译语言中,解释语言的哪些共同特征不能/不存在/确实存在?为什么?
- 这应该是社区维基,因为它没有明确的答案(我甚至不确定它是否会关闭)。请按"编辑"并选中"Communit wiki"框。
- 此外,我认为Java和C++之间的区别不值得讨论。
- 请访问stackoverflow.com/questions/2147662了解一些类似的想法!
- 答案是没有。编译器实现可以做任何解释程序实现可以做的事情。
无论源代码是否编译为本地二进制文件,某种中间语言(Java BytEcDo/IL)或解释完全不是语言的特性。这只是一个实施的问题。
实际上,您可以为同一种语言同时拥有编译程序和解释程序,例如
- haskell:ghc<->ghci
- CG:<-CH
- vb6:vs ide<->vb6编译器
某些语言特性(如eval或动态类型)可能暗示了所谓的"动态语言"和静态语言之间的区别,但如何运行它永远不会是首要问题。
- + 1。当运行编译的Java时,实际上是在解释Java字节码。除了露比是人类可读的和Java字节码不是这样的事实之外,我没有看到很多不同之处。这是不相关的。如果您考虑一下,我们可以忽略编译和解释之间的"人为"区别,使问题变得无意义,而是考虑动态/静态划分。
- @马蒂尼奥:没错。甚至可以调用一个独立的解释器,其源代码包括一个编译器;)
- 我想知道是否有可能创建一种不可能编译的编程语言。
- 此外,在底层,机器代码由处理器简单地解释。
也许问题不在于解释/编译语言(编译是模棱两可的),而在于那些有/没有自己的编译器的语言?例如,我们已经说过C++可以用一个方便的编译器在应用程序中浮动,并且反射在某些方面可能是相似的。
- 有一些C编译器库正是为此目的而设计的:因此您可以将C编译器嵌入到应用程序中,以便使用C编写脚本。libtcc就是这样一个例子。
继续从dario开始-我想你真的在问为什么编译的程序不能在运行时评估语句(例如eval)。我可以想到以下几个原因:
- 完整的编译器必须与程序一起分发(或作为程序的一部分)
- 要使eval函数能够访问所使用环境中的类型信息和符号(如变量名和函数名),必须使用可访问的符号(编译语言通常在编译时删除这些符号)编译原始程序。
编辑:如前所述,这两个原因都不能使语言/编译器无法在运行时对代码进行评估,但它们确实是开发编译器或设计语言时需要考虑的事项。
- 公共Lisp在运行时有eval,并编译了Industrial Strength实现。
- 我不是想说编译程序不可能有一个eval,我只是给出了一些为什么许多语言没有eval的原因。我会更新我的答案以澄清这一点。
- 编译器可以与运行时一起分发,就像解释程序不是解释程序的一部分一样。此外,像.NET和Java这样的现代平台将类型信息作为编译单元中的元数据(JavaCuin .NET,JAR中的JAR)携带。只去除局部变量名,因为即使局部变量本身也可以通过优化完全删除。
- 是的-关于eval,请参阅stackoverflow.com/questions/2261628/&hellip;:可能很有趣
例如,你不可能合理地执行eval,因为我认为很明显的原因:你将如何实现它?使运行时包含编译器的完整副本?每次你想评估一个字符串时(记住每次都可能不同!)将字符串保存到一个文件中,在上面运行编译器生成一个dll/共享lib,然后加载该dll/共享lib并调用代码?你不明白为什么这有点不切实际?;)
在动态语言中到处都可以发现这种情况,除了基本上在后台运行解释器外,静态代码是无法做到的。
- 我想你可以做评估。您已经说过了:让运行时包含编译器的完整副本。这就是解释语言的作用,对吧?呼叫eval只不过是呼叫解释器。因此,在编译语言中,除了调用编译器外,它不应该是其他任何东西。在.NET中,您可以直接发出IL(某种程序集/字节码),需要"将字符串保存到文件中…"。加载DLL"。这并不少见。尽管没有多少人使用"eval"这样的词,但也不是那么不切实际。
- 一个真实的例子:boo被编译并有一个解释器。我想说,在口译员的内心深处有一种逃避。还有,达里奥说的。
- 我看过一个C_的repl行为的演示。所以,eval可以用编译语言来完成。
- @约翰·费舍尔:那可能是安德斯·海斯伯格在08年的PDC(channel9.msdn.com/pdc2008/tl16)中的演讲。当时他正在使用一种"超越4.0"的C语言原型。
- 现实世界的例子:常见的Lisp。编译好的实现。
- eval的目的不是编译和运行代码,而是在当前范围内编译和运行代码。请参阅x = 41; eval("print(++x)");应打印42,并增加我们当前的x。在C中甚至没有办法接近这一点。
- @达里奥:是的,这是一个困难,主要是因为我们所知道的x在编译器进行优化之后甚至可能不存在。这并不意味着其他语言(或特殊的C编译器)不能保留这种元数据…但在这一点上,我们将推进编译/解释的含义的界限。到目前为止,我在.NET世界中看到的最好的是boo(docs.codehaus.org/display/boo/&hellip;)。但是,您必须明确什么是范围内的还是范围外的:(
- 另一个现实世界的例子,但是另一个方向:Python可以编译成某种形式的字节码。
- @达里奥,我实际上写了C代码,它克服了你提出的巨大障碍。所以我知道,不仅有一种接近的方法,而且有一种真正实现你所说的事情的方法不能用C来完成。
最初,解释语言最大的好处之一是调试。这样,在查找程序不工作的原因时,您可以获得非常准确和详细的信息。然而,大多数编译器已经足够先进了,这不再是一件大事了。
另一个主要的好处(在我看来)是,使用解释语言,您不必等待永恒的时间来编译项目来测试它。