何时使用解释型语言而不是编译型语言的示例?


11

我了解解释型语言和编译型语言之间的区别,但是如果有人可以提供一些示例,说明一种情况,一种情况是人们可能会使用解释语言而不是编译语言,而另一种情况是可能会使用编译语言而不是解释语言。真的很有帮助。

Answers:


11

(据我所知)没有解释的“语言”或编译的“语言”之类的东西。

语言指定了代码关键字,流结构和各种其他东西的语法和含义,但是我知道没有语言指定必须在语言规范中对其进行编译或解释。

现在,如果您要问的是,何时使用语言编译器和语言解释器,这实际上取决于编译器与解释器的优缺点,以及项目的目的。

例如,您可以使用JRuby编译器而不是MRI ruby​​解释器来更轻松地与java库集成。也有可能在JRuby上使用MRI ruby​​解释器的原因,尽管我不熟悉该语言,并且无法对此进行交谈。

吹捧口译员的好处:

  • 没有编译意味着从编辑代码到测试应用的时间可以减少
  • 无需为多种体系结构生成二进制文件,因为解释器将管理体系结构抽象(尽管您可能仍需要担心脚本正确地处理整数大小,而不是二进制分布)

吹捧的编译器优势:

  • 编译的本机代码没有解释器的开销,因此通常在时间和空间上都更高效
  • 互操作性通常更好,与脚本进行过程内互操作的唯一方法是通过解释器而不是标准FFI
  • 能够支持尚未编译解释器的体系结构(例如嵌入式系统)

但是,我敢打赌,在90%的情况下它会更像这样:我想用blub编写该软件,因为我很了解它,它应该做得很好。我将使用blub解释器(或编译器),因为它是在blub中编写软件的公认方法。

因此,TL; DR基本上是针对您的特定用例,对解释器与编译器进行了逐案比较。

同样,FFI:外来功能接口,换句话说就是用于与其他语言进行互操作的接口。在Wikipedia上阅读更多内容


2
据我所知,某些操作系统的脚本语言(例如UNIX的ksh)无法编译。
NoChance 2012年

@delnan,我的意思是不能通过我所知道的商业或免费软件进行编译,而不是由于技术原因无法对其进行编译。
NoChance 2012年

3
@EmmadKareem没有“无法编译”之类的东西。您编写了一个程序,该程序以语言Li读取程序,并以语言La输出等效程序。这就是编译器,即编译器。我不愿意调用图灵完整性,因为在实践中这是一个红鲱鱼,但是每个程序最终都会变成一系列机器代码指令。如果所有其他方法均失败,请展开解释器循环(并简化结果代码以删除不再需要的部分)。如果解释器是用没有解释器的语言编写的,请重复此操作,直到您用编译器击中某些东西为止。

1
(我编辑了我的评论以更好地表达它,但是显然我采取的行动为时已晚。)@EmmadKareem是的,显然,某些语言从未通过编译器实现。但是我看不出这有什么关系。这样做始终是可行且可行的,并且可以随时进行一些工作。这是要点的结果,要点是,语言既不是固有地编译也不是解释的,并且可以以两种方式实现。顺便说一下,还有其他许多方式(可以说是较小的变体和混音)。

2
@EmmadKareem如果需要的话,可以采用ksh语言规范并编写一个编译器来读取它并生成本机二进制文件。在这里,我的意思是正在编译或解释的语言不在语言的定义中。
吉米·霍法

8

这里重要的一点是,许多语言实现实际上都是两者的某种混合。今天,许多常用语言的工作方式是将程序编译为中间格式(例如字节码),然后在解释器中执行。这就是通常实现Java,C#,Python,Ruby和Lua的方式。实际上,这可以说是当今大多数语言的实现方式。因此,事实是,当今的语言既可以解释也可以编译其代码。这些语言中的某些具有附加的JIT编译器,可将字节码转换为本地代码以执行。

我认为,我们应该停止谈论解释型和编译型语言,因为它们已不再是区分当今语言实现复杂性的有用类别。

当您询问解释型和编译型语言的优点时,您可能会说其他的意思。您可能会询问静态/动态类型的优点,分发本机可执行文件的优点,JIT和AOT编译的相对优势。这些都是与解释/编译混为一谈的问题,但是是不同的问题。


2

首先,可以同时理解和编译一种编程语言。解释和编译只是从源代码生成可执行代码的方法。使用解释器,解释器读取和解释源代码,然后解释器在解释代码时执行代码。另一方面,编译器读取源代码并从源代码生成可执行的二进制文件-以便可以独立地将程序作为单独的进程运行。

现在,在任何人都知道之前……是的,可以解释C / C ++ / C#/ Java,是的,可以编译JavaScript和Bash脚本。但是,对于这些语言,是否有可用的解释器或编译器是另一个问题。

现在要实际回答这个问题,我们何时将使用“解释语言”而不是“编译语言”。这个问题本身有点令人困惑,但是我认为这意味着什么时候应该首选解释而不是编译。编译的缺点之一是由于编译过程会产生一些开销-源代码必须编译为可执行的机器代码,因此它不适合在调用源代码执行程序时需要最小延迟的任务。另一方面,由于解释源代码的开销,编译后的源代码几乎总是比等效的解释源代码更快。另一方面,解释器可以调用和运行源代码 具有很少的调用开销,但以运行时性能为代价。

最后,几乎不可能提及任何确定的用例何时一个接一个地使用,但是例如(对于我来说,这是非常不现实的)情况是当程序源代码在程序调用之间动态变化时,并且编译的开销也是高是可行的选择。在那种情况下,可能需要解释源代码而不是编译。

但是,有些事情可以视为真实示例:部署后的hidnig源代码。本机开发人员使用已编译的代码来部署程序和数据的可执行Macine代码。使用解释后的代码,必须部署源代码本身,然后可以对源代码本身进行检查和反向工程,而所需的工作要比对本机机器代码进行反向工程的工作量少得多。一个例外是像C#和Java这样的语言,它们会编译为即时语言/字节码(对于C#为MSIL,对于Java为Java字节码),然后在运行时“及时”部署和编译语言,就像解释器一样。但是,存在用于MSIL和Java字节码的所谓反编译器,它们可以以相对较高的精度重构原始源代码,因此,对此类产品进行逆向工程要比在本机机器代码中部署的逆向工程产品小得多。


1
您的观点不错,但作为我的学究,我对某些措辞表示怀疑(均指第三段):1.解释器不编译。2.糟糕的非优化编译器被高度优化(尤其是基于字节码的)解释器所击败是可以理解的(尽管这些情况很少见)。如果您将JIT编译器算在解释器下(这我不愿意这样做,但是有些人会这样做),那么这将变得更加困难。

@delnan措辞不好,我不是说英语的人。但是,据我所知,第三段并不意味着解释器可以编译。对于第二点,我强调了等同于强调已编译和解释后的代码的相似性的词,以排除较差的编译器与高性能解释器的情况,也许我不清楚,但是我看不到它。合理地专注于解释这种极端情况,因为它对通过编译或迭代解释源代码的执行之间的区别没有任何帮助
zxcdw 2012年

抱歉,不要紧记第一点,我误读了一些内容。Mea culpa。关于第二点:我采用“等效”来表示被解释或编译的代码(比较编译器和解释器没有多大意义,因为它们做的根本不同。)我不认为应该像我的示例那样浪费时间来描述异常的情况,但是我宁愿放弃“总是”,而使用这样的措辞,该措辞首先解释了为什么可以更快:没有翻译器开销[应该是定义的IMHO],并有机会在运行前进行优化。

1

当您使用解释语言时,我可以想到以下情形:

  • 没有编译器的地方,例如Linux / Unix shell脚本
  • 快速而肮脏的脚本可以解决一些问题
  • 使编写动态HTML页面更容易并且通常像JSP(Tomcat将其编译为可运行的servler),PHP,ASP等解释的语言。

当您要编译代码时,我可以想到以下情形

  • 您需要分发二进制文件,因为您的应用程序是开源的,并且您不想泄露源代码。
  • 速度,就像嵌入式系统之类。
  • 您需要一定级别的代码类型安全性,只有具有严格类型化语言的编译器才能提供给您。编译器会在源代码的每个细节中公开错别字,而在解释程序中,错别字可能会在生产代码中未被发现。
  • 大型,复杂的系统:除了已编译的二进制文件外,无法将OS或办公套装想象成什么。
  • 您希望消除所有细微的开销,并且需要与汇编器片段(在任何类型的运行时,尤其是在解释器中很难)进行良好的通信(这一点由@delnam注释引起)

3
语言解释器使语言的输入方式也一样强。Haskell具有非常强的类型,您可以使用GHCI对其进行有效解释。强/弱类型输入是语言的各个方面,而不是编译器或解释器的各个方面。
吉米·霍法

1
-1关于编译专家:(1)编译代码并不能防止逆向工程,它只是使其变得更难。(2)编译(消除解释程序的开销,自动优化应用程序代码)只是性能的一种来源,而人类专家的手动大规模优化已超越了编译。(3)类型检查通常与编译结合使用,但与此无关。类型检查器是静态分析过程;它可能在不发出代码且未解释代码的情况下发生。(4)似乎很虚假。您“无法想象”吗?为什么?需要什么?

1
只要另一个程序中有解释器,就会存在其他解释语言。每当使用解释器模式时,都会有某种复杂的解释语言。

3
“脚本”并不一定要解释。许多“脚本”语言被编译为字节码,然后执行虚拟机(请参阅lua,perl,python,ruby)。除了进行编译时,此与Java之间没有真正的区别。

3
+1,我认为这是OP真正想要的答案,尽管指出的问题可能并非100%正确,但实际考虑至少有95%正确。
布朗

1

最后,最大的权衡是在生产率(您必须编写多少行代码)和性能(程序将执行多快)之间进行权衡。

因为解释语言在转换为CPU信息时具有更多信息,所以它们可以依赖反射和动态类型,从而大大提高了生产率。解释语言的另一个优点是,它们独立于平台,因此只要有平台的解释器即可。

由于CPU不得将语言代码转换为机器代码并同时运行代码,因此在解释的情况下,编译后的语言将产生更快的程序。同样,使用编译语言构建的系统更安全,因为它可以在编译时检测到问题,这基本上意味着您在键入错误时(使用现代IDE)会看到错误,而不是仅在实际运行程序时看到错误(当然,这不能解决逻辑错误)。

知道这一点,解释语言适用于:

  1. 生产开发:快速的Web开发(PHP,Javascript)或用于原型开发。
  2. 跨平台 例如,每个浏览器(包括移动浏览器)都支持JavaScript。

编译语言在以下情况下适用:

  1. 性能至关重要(操作系统)或资源稀缺(微控制器)。
  2. 要构建的系统很复杂;在构建大型系统(企业系统)时,必须使用编译语言来处理许多可能以解释语言显示的错误。复杂的程序也需要很多资源,而且平衡也倾向于编译语言。

-1是因为您暗示所有解释语言都是动态类型,所有编译语言都是静态类型,这是完全不正确的。
丹尼尔·普赖登

@DanielPryden那么,几乎所有的解释语言都是动态类型的,而编译语言是静态类型的,这一定是纯巧合的吗?动态类型模型适用于解释语言是否是巧合?
m3th0dman 2012年

由于各种原因,存在相关性,但这不是必需的。实际上,这已经在StackOverflow上被问到了:为什么解释型lang在编译时具有强类型,而它们大多是ducktyped?
丹尼尔·普里登

1
Erlang被编译并动态键入。Haskell是静态类型的,可以进行编译或解释
Zachary K

1
@ZacharyK Erlang有一个运行时系统;Haskell在大多数情况下都已编译(已编写程序)。
m3th0dman '11

1

除了其他人提到的原因外,还有一个特别重要的用例,它可以选择一种特殊的解释而不是任何形式的编译或任何混合方法。

如果将编程语言用作通信协议,并且在响应延迟很重要的情况下,避免浪费时间进行编译和任何可能的预处理就更有意义了。

例如,这适用于代理语言,或者适用于通常如何使用Tcl / Tk的方式。

坚持解释的另一个可能原因是,使用语言解释器来引导自身或使用更精细的高级语言进行引导时,其解释性比引导过程的性能更为重要。

对于几乎所有其他可能的用例,编译(或混合方法)更合适。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.