为什么所有流行脚本语言的解释器都是用C编写的(如果不是C那也至少不是C++)?

7
我最近提出了一个关于从C++转向C编写解释器以获得速度的问题,并收到了一位评论者的评论,问我为什么会选择C。
所以我发现我实际上不知道为什么 - 除了C++面向对象系统具有更高的抽象性,因此更慢。
  • 为什么所有流行脚本语言的解释器都是用C而不是C++编写的?

如果您想告诉我其他语言的解释器不是用C编写的,请将问题中所有出现的popular scripting languages替换为Ruby、Python、Perl和PHP


2
C++ 实际上并不比 C 慢多少;只是用 C++ 编写跨平台应用程序比用 C 更难,并且 C 有更多的库可用。 - Sasha Chedygov
我当然是指“从C++代码”。 - anon
8个回答

13

C语言是一种非常古老的编程语言,因此几乎支持所有可用的系统。因此,对于任何需要在各个平台移植的项目来说,C语言都是一个不错的选择。


9
Ruby可以追溯到1995年。如果你在1995年编写解释器,你有哪些选择?Java也是在同一年发布的。(而且在v1.0中非常缓慢,在很多方面都不值得使用)
C++还没有标准化,对它的编译器支持非常粗糙。(它也还没有过渡到我们今天使用的“现代C++”。我认为STL也是在这个时候提出要进行标准化的。但实际上直到几年后才被添加到标准中。即使添加了STL,也需要几年时间:1)编译器跟进,2)人们习惯这种通用编程风格。当时,C++首先是一种面向对象的语言,在许多情况下,这种C++风格比C要慢得多。(在现代的C++代码中,这种性能差异基本消除了,部分原因是更好的编译器,部分原因是更好的编码风格,更少地依赖于OOP构造,更多地依赖于模板和通用编程)
Python始于1991年。Perl甚至更早(1987年)
PHP也是来自1995年,但是,重要的是,是由一个几乎不懂编程的家伙创建的。(当然,这在许多重要方面塑造了语言)
你提到的语言之所以使用C开始,是因为C当时是可移植、未来性强的平台最佳选择。
虽然我没有查过这个,但我愿意打赌,除了PHP的情况,它更多地受无能而不是其他任何事情的影响,其他语言的设计者之所以选择C,是因为他们*已经知道它。所以也许这个教训不是“C是最好的”,而是“你已经知道的语言是最好的”。
选择C经常被选择的原因还有其他:
  • 经验和易用性:C语言是一种简单的语言,相对容易上手,降低了入门门槛。它也很流行,有很多经验丰富的C程序员。这些语言之所以变得流行可能只是因为很容易找到程序员来帮助开发解释器。C++学习和使用起来更加复杂。今天可能不会成为问题,但在10或15年前呢?
  • 互操作性:大多数语言通过C接口进行通信。由于您的新语言将依赖其他语言编写的组件(特别是在早期版本中,当语言本身受限且库很少时),调用C函数总是简单易行的。所以既然我们肯定会有一些C代码,那么将整个程序都用C编写可能会很诱人。
  • 性能:C语言不会让你遇到太多麻烦。它并不能神奇地使你的代码快速,但可以实现高性能。当然,C++或其他许多语言也可以做到。但对于C语言也是如此。
  • 可移植性:几乎每个平台都有C编译器。直到最近,C++编译器还非常难找到。

这些原因并不意味着C语言实际上是编写解释器(或任何其他东西)的优越语言,他们只是解释了一些导致其他人使用C语言编写的动机。


7

我猜测这是因为C语言几乎是唯一一个在现有平台上都有相对标准的编译器的语言。


3
我猜测这部分原因是因为1998年的C++直到1998年才标准化,使得实现可移植性变得更加困难。
你列出的所有语言都是在那个标准化之前开发的。

3
为什么所有流行脚本语言的解释器都是用C而不是C++编写的?
您为什么认为它们是用C编写的?在我看来,大多数脚本语言的实现都是用其他语言而不是C编写的。以下是几个例子:
Ruby:
BlueRuby: 用ABAP编写 HotRuby: JavaScript Red Sun: ActionScript SmallRuby: Smalltalk/X MagLev: Ruby, GemStone Smalltalk Smalltalk.rb: Smalltalk Alumina: Smalltalk Cardinal: PIR, NQP, PGE RubyGoLightly: Go YARI: Io JRuby: Java XRuby: Java Microsoft IronRuby: C# Wilco Bauwer原始的IronRuby: C# Ruby.NET: C# NETRuby: C# MacRuby: Objective-C Rubinius: Ruby, C++ MetaRuby: Ruby RubyVM: Ruby
Python:
IronPython: C# Jython: Java Pynie: PIR, NQP, PGE PyPy: Python, RPython
PHP:
P8: Java Quercus: Java Phalanger: C#
Perl6:
Rakudo: Perl6, PIR, NQP, PGE Pugs: Haskell Sprixel: JavaScript v6.pm: Perl5 Elf: CommonLisp JavaScript:
Narcissus: JavaScript Ejacs: ELisp Jint: C# IronJS: F# Rhino: Java Mascara (ECMAScript Harmony参考实现): Python ECMAScript 4参考实现: Standard ML
HotSpot JVM是用C++编写的,Animorphic Smalltalk VM(由HotSpot和V8衍生而来)是用C++编写的,Self VM(基于Animorphic Smalltalk VM)是用C++编写的。
有趣的是,在许多上述情况下,那些不是用C编写的实现实际上比用C编写的实现更快。

作为两个使用C语言编写的实现示例,可以看一下Lua和CPython。在这两种情况下,它们实际上是用非常古老版本的C语言的一个小子集编写的。原因是它们希望具有高度的可移植性。例如,CPython可以运行在没有C++编译器的平台上。此外,Perl是在1989年编写的,CPython是在1990年,Lua是在1993年,SpiderMonkey是在1995年编写的。而C++直到1998年才被标准化。


+1 很有趣。但是你注意到问题中使用了“populat”这个词吗 :-) - anon
3
@Neil:我会说Ruby、Python、PHP和Perl非常受欢迎,实际上OP在他的问题中特别列出了这四个。而JavaScript几乎是有史以来最受欢迎的编程语言(至少对于“编程语言”的更保守定义而言,否则最受欢迎的将是Excel)。 - Jörg W Mittag
2
@Jorg 是的,这些语言很受欢迎,但我猜想你提到的特定实现并不占大多数。 - anon
2
@Neil Butterworth:同意。实际上,这个答案相当误导人,因为它没有列出任何这些语言的规范、最常见或原始实现。大多数这些实现是为了某种目的而创建的,并且如果它们被知道的话,就是因为在该语言或VM中有一个实现。 - intuited
@intuited:问题没有提到任何关于“规范的”,“最常见的”,“原始的”或“流行的”实现。它只是说流行脚本语言的解释器是用C编写的,但这不是真的,因此使问题的前提无效。例如,在Ruby中,80%目前存在的解释器不是用C编写的。在Python中,约40%不是用C编写的。JavaScript最接近“规范”的实现是参考实现,它们是用Standard ML、Python和(将来)ECMAScript编写的。 - Jörg W Mittag
显示剩余2条评论

2

与C语言相比,C++的复杂性很大 - 许多人认为它是现有最复杂和容易出错的语言之一。

C++的许多特性也存在问题 - STL在许多年前被标准化,但仍缺乏一个优秀的实现。

OOP确实很棒,但在许多情况下,它并不能弥补C++的不足。


1
STL没有很好的实现?那么所有流行的编译器都提供了什么? - jalf
1
有人正在发布STL的实现,但它的优劣是另一回事。过去我曾经作为C++开发人员工作了几年。在我们公司最大的项目之一中,CTO禁止使用任何STL类。最简单的例子是他注意到使用string类与使用字符数组的原始数组相比存在严重的性能问题。而且我们使用STL时不仅仅是性能问题。我们使用的是GCC,但CTO说他已经测试了其他STL实现,其中有些是有bug的... - Bozhidar Batsov
@Bozhidar Batsov:这是多久之前的事了? - Viktor Sehr
1
那么你的推理实际上只是“一个人曾经告诉我它很糟糕”吗?有些人会说,实际上亲自测试一下会产生更可靠的数据。 ;) - jalf
其实很多人跟我说过类似的话,这让数据更加可靠,并且倾向于只探索我感兴趣的事情 - 我宁愿花时间与Lisp相处,也不愿意与C++为伍;-) - Bozhidar Batsov

1

大多数著名的编译器书籍都是以C语言为例子编写的。 此外,两个主要的工具lexx(构建词法分析器)和yacc(将语法翻译成C语言)也支持C语言。


0
如果问题是关于为什么选择C而不是C++,答案在于当你实现一个脚本语言时,C++对象模型会妨碍你。它非常受限制,以至于你将无法将其用于自己的对象。
因此,你只能将其用于内部,而在那里,通常使用比较简单的C语言比使用C++更容易移植和分发。
在C中实现脚本语言唯一的问题是缺少协程支持(你必须以某种方式切换堆栈指针),并且最重要的是没有办法进行异常处理,这会带来很多开销(与C++相比)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接