我想知道以下问题:
几乎所有现有语言 实现/写一些小的 低级语言的数量?对于 大多数语言都是写的 在C? C ++是用C语言编写的吗?
之间是否存在某种关系 实施关系和 子集/超集的概念 语言
在语言功能方面,有些 语言比其他语言更多。 在某些情况下,有些人拥有全部 其他一些功能,例如, C ++是否具有C的所有功能?
之间是否存在某种关系 子集/超集关系 一组功能和 子集/超集之间的关系 语言
谢谢和问候!
答案 0 :(得分:19)
“某些语言是另一种语言的子集/超集”是什么意思?
语法上语言A是语言B的子集,如果在语言A中有效的每个程序在语言B中也是有效的。语义上,如果它是语法子集,则它是子集,并且每个有效的A程序也表现出相同的语言。语言B中的行为。
可以用数学定义吗?它与基本集理论中的子集/超集概念有关吗?
语法子集:如果P_A
是语言A中所有有效程序的集合,P_B
是语言B中所有有效程序的集合,则语言A
是语法子集语言B
的确切P_A
是P_B
的子集。
语义子集:让A(p)
成为描述语言A中程序p
的行为的函数,B(p)
描述语言B中程序p
的行为。 A是B的子集,当且仅当p
定义了A(p)
时,B(p)
也被定义,A(p) = B(p)
。
几乎所有现有语言都是用少量低级语言实现/编写的吗?
这取决于你对“几乎所有”的定义当然,但我倾向于拒绝。许多编译器和解释器都是用C和C ++编写的(仅仅因为许多软件通常用C和C ++实现),但到目前为止还不是全部。
例如,大多数语言是用C语言编写的吗? C ++是用C语言编写的吗?
正如已经在评论中指出的那样,C ++语言不是一种软件。 g++
这是GNU C ++编译器是用C语言编写的,但也有C ++编译器,它们用不同的语言编写(可能)。
在语言功能方面,某些语言比其他语言更多。在某些情况下,有些功能具有其他功能,例如,C ++是否具有C的所有功能?
是(除非您将简单性视为一项功能)。
在特征集和语言之间的子集/超集关系方面,子集/超集关系之间是否存在某种关系?
如果某种语言是另一种语言的超集,那么该语言功能的集合也必须是其他语言功能的超集(除非你将简单性或类似“语言不允许X”的内容称为功能)。
然而,这不适用于其他方向(即因为A的特征是B特征的超集,A不必是B的超集)。
答案 1 :(得分:4)
我想接受这个:
几乎所有现有语言 实现/写一些小的 低级语言的数量?对于 大多数语言是写的 C? C ++是用C语言编写的吗?
据我所知,在实践中,几乎所有源自C语言的语言都是用C语言编写的,因为C在某段时间内非常流行 - 直到他们准备好实现自己的编译器。大多数编译为本机代码的语言都是自己实现的 - 也就是说,现代C ++编译器是用C ++编写的。这是通过使用已知为良好的编译器的先前版本(LKG或“Last Known Good”编译器)编译新编译器来实现的。我知道Visual C ++编译器是以这种方式完成的,我记得有些Haskell IDE也是这样做的,甚至是PROLOG。最初的C ++编译器是用C语言编写的,但由于C ++本身就是一种通用的强大语言,人们在其中编写了C ++编译器。
当然,对于不编译为本机代码的语言来说,这个过程是不可能的,因为它们必须总是有一些底层解释器或虚拟机来执行不能用该语言编写的代码,从而无法使本机语言无效使用托管或解释语言。
之间是否存在某种关系 实施关系和 子集/超集的概念 语言
是的,有。如果你正在实现C#,那么为什么要放弃多年的C ++快速制作多态函数调用的经验呢?最简单的做法就是回到实现 - 而且我的理解是,在.NET框架上运行的C#中,确实发生了这种情况 - 它们使用的是一种基本上直接来自C ++的实现。如果您正在实现某种语言已经存在的语言功能,那么如果您从头开始实施新的实施,那么您将失去经验和创新。当然,如果这些实现是专有的或者某些东西,那么这是不同的,但总的来说。
还有其他方面吗? 表征之间的关系 语言
是的,有。最明显的一个是语法 - 考虑C,C ++,C#和Java之间的句法关系,尽管Java和C#显然不是C的超集。然后考虑软件开发中的主要问题的方法。例如,Java和C#都是静态类型,垃圾收集,基于虚拟机的语言。然后你可以考虑设计错误。在我看来,设计错误是两种语言比实际应用更密切相关的最大暗示之一。在这里,您可以再次考虑Java和C#。协变阵列被打破。 Giraffe[]
不是Animal[]
,但Java和C#都允许转换。这是一个明显的设计错误,但两种语言都有它,这表明它们的关系太密切了。
当然,C ++在这里有一个独特的位置,我不知道任何直接接替另一种语言的语言,C / C ++是你能找到的最接近语言超集的东西。 C ++标准委员会仍在标准化C ++中的功能,纯粹是为了保持与C99的兼容性。
答案 2 :(得分:3)
对形式语言有严格的定义 - 语言L1是语言L2的子集,当且仅当每个格式良好的L1公式都是一个格式良好的L2公式时。
在编程语言的情况下,“格式良好的公式”意味着语法上有效的程序,您可能希望或不希望您对“子集”的定义不仅表示L1的有效程序也是有效程序L2,但它在L2中具有与L1中相同的语义。由于C和C ++都具有未定义行为的语义概念,因此您还可以说,如果L1是L2的子集,则只需要每个具有已定义行为的语法有效的程序在具有相同定义行为的L2 - 不要求L1中具有UB的每个程序在L2中也具有UB。形式语言不定义语义,只定义语法,这就是为什么这不是第一个定义的一部分。
C ++并不是真正的C的超集。编写有效的C程序非常容易,这些程序不是有效的C ++程序,也许最明显的方式是C ++保留了一些未在C中保留的关键字,所以一个有效的C程序使用new
作为变量名是无效的C ++。在实践中,人们谈论一种稍微宽松的语言概念,并且可能会说C ++“几乎”是C的超集,意味着许多有效的C程序也是有效的C ++。当然,松散的概念可能导致错误(通信和编程)。
当您尝试更改语言(创建新版本)同时保持所谓的“向后兼容性”时,正确定义子集非常重要。为了使您的新版本真正向后兼容旧版本,新版本的实现应该像以前一样完全运行旧版本的每个程序(至少,就语言定义其含义而言),因为这意味着用户可以更新到新版本,所有旧程序仍然可以工作(至少,假设他们只依赖于保证的行为)。这同样适用于库API,除了你不担心整个语言,你只是担心与你的界面的交互。
答案 3 :(得分:2)