表达力具体指的是什么?


34

维基百科将表现力定义为:

..可以用该语言表示和传达的思想的广度。

“想法”是否指我们可以与机器通信的事物(操作,结构,算法等?)?还是它是指可以被捕获并与其他人交流的“人类”概念?

如何评估和衡量表达能力?

例如,如果我们采用JavaScript之类的语言,并对变量名称施加了怪异的限制,例如变量必须是一个8位数字,并带有下划线,match/^_[0-9]{8}$/,我们会失去表达能力吗?

还是那只会是荒唐而又烦人的?


澄清:

表达能力是由语言固有的一般思想衡量的:

  • 整数和字符串
  • 循环
  • 有条件的

或该语言可以代表的特定,独特想法的数量:

  • 整数1,2 ... 2 ^ 32
  • 包含“狐狸怎么说”的字符串 和“ wah pah pah pah pah pah pow”
  • 每个青蛙我的收藏青蛙
  • 如果青蛙绿色的,或者做什么,那就做什么

3
应该注意的是,在给定范围内将程序限制为最多1亿个变量会限制表达能力。例如,可能无法实现Firefox。;-)
R.,

1
请注意,尽管已标记了这种“编程语言”,但编程语言并不是唯一可以讨论其表达能力的计算机语言。确实,您链接到的页面以Web本体语言为第一个示例。
乔恩·汉纳

Answers:


39

关于表达性的里程碑式论文是Matthias Felleisen(1991)发表的《关于编程语言的表达力》。它包含语言表达能力的严格数学定义。

直观地讲,如果每个可以用语言A编写的程序也可以只用局部转换就可以用语言B编写,但是有些用语言B编写的程序就不能在不改变全局结构的情况下用语言A编写(即纯粹是局部变换),那么语言B比语言A更具表现力。

此定义的一个不错的特性是它承认存在这样的可能性,即存在成对的语言,其中X中存在无法用Y表示的程序,而Y中存在无法用X表示的程序,因此这些语言是不同的,但是都不是语言比其他语言更具表现力。这与我们在现实世界中的经验非常吻合,因为有些语言擅长某些方面,而有些语言擅长其他方面,并且两种语言通常都不比另一种“更好”。


那么,(尚未看过本文)表达能力是关于您可以向机器表达的内容,而不是与阅读源读者相对的内容?这是您可以指示硬件做什么的度量?无法衡量您可以在代码中保留或传达多少“人性化”想法?...也许我需要问另一个问题;但是,如果是这样,它与我们也谈到的“功能”有何不同?
svidgen 2014年

也许我在OP中的例子很糟糕。考虑带有数组的语言A和B;但是,语言A也有结构。无论哪种语言,我都可以Point使用2D数组的数组表示一系列。但是,A的优点是让我将Pointa 表达为更易理解的概念。是一个更具表现力?
svidgen 2014年

@svidgen因为所有图灵完备的语言在计算上都是等效的,所以从理论上讲,所有可能编写的程序集都是相同的。根据上述定义,如果必须重组用B编写的程序以使其适合A,则语言B比A更具表达力。(不仅逐行更改语法,而且引入新的类,循环等。考虑重写Python计划在Java 7中使用lambda表达式,mapfilter,一流的类型/方法/函数,也许一些eval,更不用说元类魔法或动态创建的类型等
marczellm

@marczellm那么,表达性所指的“想法”是语言本身的构造吗?例如,有条件的想法?循环是个主意吗?弦吗?数?等等。?
svidgen 2014年

1
@Jörg可以在回答中举一个例子吗?这是一个很可爱的定义,但实际上并不能解决这个问题。
svidgen 2014年

10

维基百科将表现力定义为:

让我们重新阅读该页面。首先要注意的是它说的是“语言”,而不是“编程语言”,并且它的大多数示例不是编程语言,例如,给出的第一个示例是OWL2 EL和OWL2 RL的比较,两者都是本体语言。

可以将这一概念应用于编程语言,也可以应用于模式匹配语言,标记语言,查询语言,视觉样式表语言,正则表达式(以及它们所引用的所有常规语言)等等。甚至可以提到自然语言(如英语)的表达能力,这通常是非常非正式的,但是在考虑与自然语言处理相关的问题时会更加认真。

“想法”是否指我们可以与机器通信的事物(操作,结构,算法等?)?还是它指的是可以被捕获并与其他人交流的“人类”概念?

它指的是可以用该语言表达的内容,纯粹被视为事物本身。

例如,(在我的示例中,我将始终使用javascript,因为您的问题表明它是您所知道的一种语言)考虑使用javascript语句:

var x = 3 + 4;

这表示已计算3和4的值之和,并且该值与标签相关联 x给定名称空间范围内的。

如果我们销毁了世界上所有的计算机,并将这些代码写在一张纸上,那么在javascript中,它仍然具有相同的含义。我们将无法在任何东西上运行这样的代码,但是语言的抽象定义仍然是我们可以谈论的话题。

这似乎有些古怪,但实际上,语言是可以抽象地推理而不考虑真实计算机的事物,这一点实际上非常重要。一方面,人们对计算机语言在实践中尚不可行的理论要点进行推理,这是使我们走到今天的现状之一。计算机需要计算机科学,但是计算机科学不需要计算机,仅需要计算概念。

当然,我们确实在现实世界中使用计算机,而如今,有很多人在实践中使用计算机,而不是一些专家在理论上讨论它们。您链接到的页面显示:

术语表达能力可以在一定范围内使用。它可能意味着可以用该语言表达的想法的度量:

  • 不分轻重(理论表现力)

  • 简洁明了(实用的表现力)

第一种意义在涉及语言及其含义的形式描述的数学和逻辑领域中占主导地位,例如形式语言理论,数学逻辑和过程代数。

在非正式讨论中,该术语通常是指第二种意义,或两者兼有。讨论编程语言时通常是这种情况。已努力将这些术语的非正式使用形式化

在该术语的这两种用法中,第一种的实际影响仅与与可以传达给计算机的内容有关。

第二个方面在阅读和书写方面都与人类的理解有关,尽管这样做的程度在使用之间存在很大差异,因为它们是非正式的,因此没有严格定义。

例如,如果我们采用JavaScript之类的语言,并对变量名称施加了怪异的限制,例如变量必须是一个8位数字,并带有下划线,match /^_[0-9]{8}$/,我们会失去表达能力吗?

根据正式定义,我们没有丧失表达能力:我们只能使用1亿个变量,但是如果确实需要,我们可以通过创建对象以在新创建的命名空间中容纳更多变量来解决这个问题。因此,今天用javascript编写的任何程序都可以以这种新形式重写,因此它们具有同等的表达力。

根据非正式的定义,我们已经失去了一些,但是多少取决于我们的非正式程度,这将有所不同,因为您再也无法说出信息使用的“规则”是什么。我们可能会说我们损失了很少的钱,因为在同一个命名空间中具有超过1亿个变量的程序必须重写,而不仅仅是简单的替换。更加非正式的用法将再次指代这种笨拙的变量名称对人类全面性的精神影响。

还值得注意的是,人们会非正式地考虑根本不属于该语言的事物。考虑从创建到现在的Javascript更改。

按照最正式的定义,表达能力几乎没有变化。毕竟,图灵完全是完整的。

通过更非正式的定义,它在某些事情(例如数组操作,异常处理以及正则表达式的包含(也许是最重要的))中已变得更具表达性。尽管它们通常可以在几行之内完成一秒钟的执行时间,但它们并没有执行以前用javascript无法完成的任何工作,这需要数千字节的代码才能用javascript1.0编写,而且运行时间很长。

再次根据非正式的定义,它与javascript在浏览器中的首次使用(可以更改表单输入的值, document.write而页面首先被解析并移动到新位置或在历史记录中来回或前进,到今天为止(几乎可以更改页面上的任何内容,包括基于服务器调用中的数据),这绝对是巨大的,尽管其中大多数与javascript不相关,但与对象模型和API有关而不是语言(例如IE中的vbscript同样从这些更改中受益)。

在我看来,最后的使用是非正式的,以至于不能真正正确,但这就是非正式定义的问题。

按照正式的定义,它实际上并没有变得更具表现力。


2
“计算机需要计算机科学,但是计算机科学不需要计算机”我喜欢
chbaker0 2014年

关于变量命名限制,引用外部思想(事物的本地语言名称)的能力与语言表达思想的能力无关吗?...也许更多地是问题的根源:我们正在谈论的想法只是表达一般的语言结构吗?例如,加法,减法,否定,数组,类等?相对于我们可以用语言表达的特定想法?例如,类型为的数组fishiesFish
svidgen 2014年

您可以查看我的编辑内容以进行更多说明。...听起来像是您在说这两者(指我的编辑);但是第一个列表是“正式”,第二个列表是“非正式”。如果是这样,是否有规范地将其无条件地用于对话中?还是……您只是倾向于要求澄清?
svidgen 2014年

4

我认为可变命名规则并不能真正体现“表达能力”的含义。我认为“表达力”是指更基本的东西。例如,考虑使用带有Linq的C#与之前的Linq的C#。添加Linq后,就可以直接在C#中编写类似SQL的查询。这比以前的替代方法要优雅得多,例如,将SQL放入字符串文字中,然后将其传递到服务器,或者使用“ for”遍历集合。

另一个很好的例子可能是具有基于原型的继承的语言。在这些语言中,可以在运行时将新方法简单地添加到实例甚至类(通过“给定的语言命名”,无论其名称如何)。您实际上不能在C ++或C#中做到这一点。与基于原型的语言相比,它们缺乏这种表达能力。(C#确实具有扩展方法的概念,可以肯定地说可以增加表达能力。)


0

正如Wikipedia文章所引用的那样,表达能力是指可以用该语言表达的程序集。您认为是“编程语言”的所有内容(JavaScript,LISP,C#,Perl等)基本上都是图灵完整的,这意味着它们可以表达任何被称为“可计算”的内容。

但是,应该很清楚,正则表达式不像正则编程语言那样具有表现力。此外,shell通配符的表达性不如正则表达式。

具有通用表表达式的SQL版本比没有CTE的版本更具表达力,因为CTE允许您表示递归查询,否则将无法在SQL中表达。


0

有一种更简单,更直接的方式来理解表达力,但是首先我们需要确定我们所说的语言。有两个学习语言的学科:语言学和自动机。两者都同意语言是使用级联从某些有限字母表中构造的单词(有限序列)集。通常,有趣的语言(有趣的是,我可以用一种有用的方式解释这些语言)也具有一组规则,这些规则控制着哪些单词在该语言中,哪些不在。注意,表达只有在有解释时才能存在。

通过解释,我的意思是说存在一个函数,该函数给定一种语言中的单词,从而从一组对象中选择一个对象(这对于自然语言显然是有争议的)。

但是不要被“单词”的使用误导。Java程序是Java语言中的一个词(尽管它可以跨越多个文件,这些文件包含用空格分隔的多个字符串)。

使用诸如现代编程语言之类的复杂语言来处理这个相对简单的概念会适得其反,这就是为什么我宁愿使用数学公式的原因。

  • 让我们将语言A定义为所有涉及整数加法的公式。

  • 让我们将语言B定义为涉及整数乘法的所有公式的语言。

在这两种情况下,我们都不允许使用标识元素。因此,语言A包含单词“ 1 + 1”,“ 1 + 2”,“ 1 + 3”,“ 2 + 3”等。语言B包含单词“ 2 * 2”,“ 2 * 3”,“ 2 * 4”,“ 3 * 4”等。我们还将通常的解释分配给相应符号的“ *”和“ +”(整数加法和整数乘法)。因此,“ 1 + 1”的解释为2,而“ 2 * 2”的解释为4。

现在观察到,语言A严格比语言B具有更高的表达力,因为整数确实可以将乘法强制转换为重复加法,但是通常没有办法将加法表示为乘法。


综上所述:当语言A的解释功能共享同域时,可以说语言A比语言B更具表达力,但是语言B的解释功能的图像是语言A的解释功能的适当子集。


-1

TLDR:如果某个功能缺失,但是可以用其他方式表达,那么它就不会缺乏表达能力。如果您可以在脑海中设想一种算法,甚至可以用一种语言实现该算法,但是以某种方式构造另一种语言,使其无法实现该算法,那就是表达性问题*。

变量命名限制不会降低表达能力(除非名称太少,以至于不能再表达所有算法,并且不能伪造具有数组+索引之类的变量)。

缺乏表达能力的一个简单示例是:您必须do_homeworkbring_down_trash。这很容易用代码编写:

do_homework();
bring_down_trash();

该解决方案看起来很简单,但实际上do_homeworkbring_down_trash是无序的,你也可以这样写:

bring_down_trash();
do_homework();

这同样是不精确的,因为它并不表示我们不打算执行命令。我们也不想使用线程。我们想这样说:

compiler_or_interpreter_pick_one(
    {
        do_homework();
        bring_down_trash();
    },
    {
        bring_down_trash();
        do_homework();
    }
);

据我所知,这很难用任何编程语言来表达。

一个使我烦恼不已的例子是,在Java中不可能拥有对象数组。您可以建立一个指向对象的指针数组,但是指针的内存布局不相同(提高效率)。

另一个答案为例:C ++不支持向类或实例添加方法。这是事实,但是它并不限制C ++的表达能力。

struct Extensible{
    std::vector<std::function<void(Extensible *)>> instanceExtensions;
    static std::vector<std::function<void(Extensible *)>> classExtensions;
};

您可以在该类中添加,删除和调用实例和该类的任意数量的成员函数。从技术上讲,C ++在这方面可能比实际支持该功能的编程语言更具表现力,因为在C ++中,您可以选择存储函数的方式(向量,数组,forward_list)。

*某些语言缺乏表现力。通常,它们使编写无限循环成为不可能。这可以使暂停问题解决,并允许自动证明其正确性。


2
我相当确定这是不正确的-至少这不是我所理解的。写原始的二进制磁盘是表现通过这个定义,这是荒谬的。
Telastyn 2014年

1
@Telastyn为什么这样荒谬?当然,仅将原始二进制文件写入磁盘并不具有表达能力,但是可以做到这一点的语言比其他条件相同的语言具有更高的表达能力。
nwp

我的意思是,使用硬件接口将原始位写入计​​算机的“语言”是最具表现力的语言的一个示例,因为按照定义,它可以完成计算机可以做的任何事情。它可以通过其他方式表达任何缺少的功能。根据您的定义,是一种表达性语言,我觉得很荒唐。
Telastyn 2014年

@Telastyn为什么那是最富表现力的语言?它不能表示读取数据或计算任何内容或显示图形或线程。一种只能将位写入内存和磁盘的语言的表达能力极低,我怀疑它根本没有用。
nwp

1
“通常情况下,它们使编写无限循环成为不可能。这可以使暂停问题得以解决”-如果您没有无限循环,那么根据定义,您的程序必须停止。
帕特里克·柯林斯
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.