如何验证/证明编程语言的正交性?


10

我知道正交性的概念,但是从编程语言的角度来看,有没有一种方法可以验证/证明它呢?

例如在C#中,可以使用publicstatic进行方法签名。您可以使用其中之一,也可以使用两者,并且它们不会互相干扰,因此它们彼此正交,对吗?

我的问题是,我该如何处理其余功能,尤其是互不相关的功能?

所有功能都必须共存/堆叠在一起吗?

是否有100%正交的编程语言?


从(近)开始:汇编语言?
马修·弗林

1
要实际证明某件事,您需要为其提供正式定义。而且,如果您的定义将与C#规范一样大,那么证明任何事情都将需要大量工作。
svick 2012年

Answers:


4

我不确定在像C#这样的通用高阶语言中,正交性是否可以用作有用或有效的度量标准,因为它需要区分“操作”和“操作数”,这是该语言的一小部分,不易使用在像C#这样的高级语言中可以区分。

我对正交性的理解是基于汇编语言的,其中某个特定CPU或微控制器的指令集正交性表明该CPU或控制器执行的操作是否受到数据类型的限制。在早期,这很重要,因为并非每个CPU都支持分数或不同长度的数字等运算。

在这方面,我宁愿使用Stack Machine language作为C#编译器的目标而不是C#本身来检查公共中间语言的正交性。

如果您真的对C#的正交性感兴趣,并且我在这里没有记错(出于任何目的),我建议您参考一些遗传编程算法。您可以使用它们根据给定的关键字集(甚至是无意义的关键字)生成不同的程序,并且可以自动检查它们是否可编译。这将帮助您自动查看语言的哪些元素可以组合在一起,并得出正交性度量的某些方面。


6

术语“正交性”是一个精确数学概念的外行术语:这些语言术语构成一个初始代数(在Wikipedia中查找)。

它的基本含义是“语法和含义之间存在1-1对应”。这意味着:完全有一种表达事物的方法,并且,如果您可以在特定位置放置某些表达式,那么您也可以在其中放置任何其他表达式。

考虑“正交”的另一种方法是语法遵循替换原则。例如,如果您有一个带表达式槽的语句,则可以在其中放置任何表达式,并且结果仍然是语法上有效的程序。此外,如果您更换

我要强调的是,“含义”并不意味着计算结果。显然,1 + 2和2 +1都等于3。但是,这些术语是不同的,即使结果相同,也意味着计算不同。含义是不同的,就像两种排序算法是不同的一样。

您可能听说过“抽象语法树”(AST)。这里的“抽象”一词恰好表示“正交”。从技术上讲,大多数AST实际上并不是抽象的!

也许您听说过“ C”编程语言?C类型表示法不是抽象的。考虑:

int f(int);

所以这是一个返回类型的函数声明int。指向此函数的指针的类型如下:

int (*)(int)

注意,您不能编写函数的类型!C型符号很烂!它不是抽象的。它不是正交的。现在,假设我们要创建一个接受上述类型而不是int的函数:

int (*) ( int (*)(int) )

一切都好..但是..如果我们想返回它怎么办:

int (*)(int) (*) (int)

哇!无效。让我们添加括号:

(int (*)(int)) (*) (int)

哇!那也不行。我们必须这样做(这是唯一的方法!):

typedef int (intintfunc*) (int);
intintfunc (*)(int)

现在可以,但是在这里必须使用typedef是不好的。C糟透了。它不是抽象的。它不是正交的。在ML中执行此操作的方法如下:

 int -> (int -> int)

我们在语法级别上谴责C。

好的,现在让flog C ++。我们可以使用模板来解决上述愚蠢问题,并获得ML之类的符号(或多或少):

fun<int, int>
fun< fun<int,int>, int>

但是实际的类型系统从根本上存在引用缺陷:如果T是类型,那么T&类型是?答案很不合理:在语法级别,如果您有类型U = T&,则允许U&,但这仅表示T&:对引用的引用是原始引用。太烂了!它从语义上打破了唯一性要求。更糟糕的是:T&&在语法上是不允许的:这违反了替换原则。因此,C ++引用根据绑定时间(解析或类型分析)以两种不同的方式打破正交性。如果您想了解如何正确执行此操作..指针没有问题!

几乎没有真正的语言是正交的。甚至冒充表达方式清晰的Scheme也并非如此。但是,许多优秀的语言可以被判断为“在合理程度上接近正交特征基础”,这是对语言的良好推荐,既适用于语法又适用于基础语义。


那么您认为ML比其他机器更正交吗?Lisp和Haskell呢?
Joan Venge 2012年

1
@joan:好吧,lisp没有任何功能,因此可以满足vaccuuo的要求:)
Yttrill 2012年

@joan:我不是Haskell程序员,所以很难说,但是Haskell中存在“极高级功能”表示强烈的正交性:除非有Monads或Arrows的连贯实现,否则就无法实现语言的其余部分具有实质性的“正交性”
Yttrill 2012年

您对Pascal的看法。似乎负载比C好
。–超级猫

我知道我的评论迟到了4年,但我才发现它。这个答案在几乎所有方面都是错误的。甚至整个“这都是唯一的方法!” 部分完全是错误的。您可以轻松地表示出它,而无需使用typedef示例int (*intintfunc())(int) { ... }-intintfunc是一个不带任何参数并返回指向带有1个int参数并返回一个int值的函数的指针的函数。
Wiz

4

证明正交性是负面的。这意味着您没有任何非正交的构造,这意味着证明某些东西不是正交的要容易得多。

在实践中,大多数人都在谈论编程语言的正交性,而不是完全正交。当在一个情境中做某事的知识转化为另一种情境并“达到您的期望”时,该语言就被认为是更正交的。LISP被认为是高度正交的,因为所有内容都是一个列表,但是我认为不能说它是100%正交的,因为有些冗余使其更易于使用。C ++被认为不是非常正交的,因为有很多小“陷阱”,但它们并没有像您认为的那样起作用。


3

警告,我对此主题一无所知。

快速浏览Wikipedia似乎表明正交性主要针对设计模式和系统设计。在编程语言方面,如果每个可能的动作只有一条指令,或者没有一条指令与另一条指令重叠,则该条目指示指令集是正交的。

对于C#,我想它是正交的,因为大多数语法技巧(foreach想到的)只是基础结构的特殊形式版本的前端(foreach变成for循环)。总体而言,即使语法糖提供了执行操作的其他方式,该语言也只能真正地以单一方式支持执行操作。最后,它全部编译为MSIL(或现在所说的)并且MSIL可能是正交的。

如果要说明句法糖的东西本质上是“包装方式”的“包装”,那么您可以分析语言的各种功能,省略糖,看看是否有真正重叠的结构。如果没有,我想您可以声明正交语言。

我的两分钱。


我认为,如果for和foreach两者都是语言的特征,而一种语言是另一种语言的语法糖(使用for可以实现foreach的效果),则该语言将失去其正交性。
vpit3833 2012年

不能do...while用来提供与相同的效果for吗?我从未听说过这两种语法糖。
马修·弗林

1
@MatthewFlynn:ah!它们都是语法糖,您可以将您的迭代替换为递归函数!;)
FrustratedWithFormsDesigner 2012年

2
@FrustratedWithFormsDesigner:这不只是GOTO的语法糖吗?
伊万(Ivan)

2
@MatthewFlynn do while保证单循环执行并在事后检查条件。for首先检查条件,并且不保证单次执行。
digitlworld 2012年

2

我的问题是,我该如何处理其余功能,尤其是互不相关的功能?

您继续做自己在做的事情,列举所有有效的或被禁止的组合。

就这样。做起来很痛苦。

所有功能都必须共存/堆叠在一起吗?

如果所有功能都可以划分为互不干扰的不相交的子集,那么可以肯定,所有功能都是明智的。

所有数据结构都适用于所有原始类型。所有表达式运算符都适用于所有类型。这些是正交性的常见定义。但是您可能想要更多(或更少)

但是,有时会由于操作系统或旧版库不正交而出现特殊情况。

另外,某些类型根本不是很符合标准。例如,Python允许您比较两个字典对象的“顺序”。但是字典中几乎没有“排序”的合理定义。Python定义了一个,但这是有争议的。特殊情况会使字典不通过正交性测试吗?

“正交足够”如何正交?需要看什么才能对语言的正交度感到满意。


2

在大多数编程语言中,非正交特征的列表确实很长,例如

  • 匿名类与Java反射冲突
  • 泛型和类型擦除与Java反射冲突
  • 数组由于其特殊类型而与其他对象有些不同,即使它们是对象。
  • 静态方法与实例方法不同,例如,您不能覆盖静态方法
  • 嵌套类是事后思考
  • 动态类型与静态类型对消息分发策略的影响(例如,参见C#中的这种极端情况
  • 等等

我想到的只是少数几个,但还有许多其他语言,还有其他语言。

很难确保语言功能之间没有细微的干扰。正如CAR Hoare在他的论文“编程语言设计的提示”中指出的那样:

语言设计的一部分包括创新。此活动导致孤立的新语言功能。语言设计中最困难的部分在于集成:选择一组有限的语言功能并对其进行完善,直到结果是一个一致的简单框架,不再具有粗糙的边缘。

可能要增加正交性的一个好方法是统一概念(朝@ karl-bielfeld答案的方向发展)。如果说所有东西都是列表或对象,那么冲突的机会就会更少。或者,不要将嵌套类当作事后考虑,而应将其作为核心功能。

大多数编程语言论文都在形式化语言的子集(“核心”)上证明了该语言的某些属性(例如,类型健全性)。在这里,我们应该做相反的事情,证明所有功能都是安全的。同样,这意味着应该定义“组成”的含义。这意味着“奔跑”吗?(在这种情况下,上面关于动态和静态类型的边际情况的链接是安全的)。这是否意味着“安全”?从开发人员的角度来看是否意味着可以预测?

所有这些都很有趣-但也很有挑战性。

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.