为了获得将产生所需程序行为的语法突出显示,需要键入正确的文本,这常常妨碍编程的效率。程序员只能通过神秘的文字咒语间接控制代码的颜色和格式。在本文中,我们介绍了WysiScript,这是一种新的语言,它允许通过直接应用颜色和格式来表达程序语义,从而使程序员摆脱了对文本的这种陈旧的依赖。我们描述了该语言的主要思想,并用一些示例程序展示了它的功能和易用性。最后,我们提出了一种理解程序结构的新技术,这只有通过WysiScript采取的新方法才能实现。
计算机科学基础研究中的一个重要问题是:是什么使编程语言成为编程语言?换句话说,编程语言与纯文本有什么不同?例如,考虑一下下面图1中的纯文本和编程语言的示例。
大平原是北美的一个主要地形省份,位于南部的格兰德河和北部麦肯齐河流入北冰洋的三角洲之间,东部是美国中央低地和加拿大盾,西部是落基山脉。它们的长度约为3000英里,宽度从300英里到700英里,面积约为112.5万平方英里(2900000平方公里),大致相当于美国的三分之一。美国十个州(蒙大拿州、北达科他州、南达科他州、怀俄明州、内布拉斯加州、堪萨斯州、科罗拉多州、俄克拉何马州、得克萨斯州和新墨西哥州)和加拿大草原三省(马尼托巴省、萨斯喀彻温省和艾伯塔省)的部分地区和西北地区的部分地区位于大平原范围内。一些作家把100度子午线作为东界,但更精确的是从德克萨斯州到北达科他州的向东的悬崖,通常在100度子午线的东边。在加拿大部分,大平原和加拿大盾的分界线位于北部红河以东,穿过温尼伯湖,然后向东北弯曲,穿过阿萨巴斯卡湖、大奴湖和大熊湖,到达麦肯齐三角洲以东的北冰洋。
#include<;stdio.h>;/*返回子树中的节点数。*/int COUNT_NODES(const Node*t){if(!t)返回0;返回1+COUNT_NODES(t->;左)+count_Nodes(t->;右);}/*比较两个节点并返回键较大的节点。*/Node*max_node(const Node*a,const Node*b){返回a?B?a->;键>;b-&>键?A:B:A:B;}/*返回子树中键最大的节点。*/Node*max_subtree_node(const Node*t){if(!t)return 0;return max_node(max_node(t,max_subtree_node(t->;左)),max_subtree_node(t->;right));}/*发出节点的文本表示形式。*/void emit_subtree(const节点*t){putchar(';[';);if(T){printf(";%d,";,t->;key);emit_subtree(t->;左);putchar(';,';);emit_subtree(t->;右);}putchar(';]。
仔细比较这两个示例就可以清楚地看出区别:主要的区别是编程语言有颜色和格式,显然正是这种特殊的格式赋予了编程语言强大的功能。这就是纯文本无法执行的原因-它缺少格式。(这也解释了Microsoft Excel中缺乏功能的原因。)。
传统上,编程是通过键入复杂的文本来产生适当的颜色和格式,以使程序正确工作。决定程序行为的颜色和格式只能通过调整文本来间接控制。这是一个冗长而迂回的方法(图2)。
在本文中,为了提高编程效率,我们引入了WysiScript,它允许程序员绕过键入文本的步骤,直接应用所需的格式(图3)。而且WysiScript有很多格式,这使得它比典型的编程语言更强大。
本文旨在提供WysiScript语言的一般介绍。有关该语言的更多信息以及标准参考实现,可以在http://www.zifyoip.com/wysiscript/.上免费获得
编程语言并不总是基于文本的。早期的工作探索了许多不同的范式。例如,第一个广泛使用的编程语言,为每个任务构建一台新机器,完全没有使用文本,而它流行的后继者诺尔德语则是将电线插入不同的地方。
非文本编程语言领域在20世纪50年代和60年代初在东方集团相当流行。1953年,保加利亚计算机科学家迪米塔尔·拉贾科夫(Dimitar Radjakov)开发了一种编程语言,其依据是送到计算机机柜一侧的一系列螺丝的时间和强度[5];保加利亚的计算机多年来一直依赖这一系统。1957年晚些时候,南斯拉夫数学家DraganaŠimunović提出了一种语言,在这种语言中,程序是将粗糙和光滑的物体扔进皮包中的集合[6],但这一计划从未得到令人满意的实施。1962年,苏联生物化学家安德烈·米哈伊洛维奇·图拉波夫斯基(Andrey Mikhailovich Turapovsky)首次描述了一种功能齐全的气味语言[7]。
然而,由于当时的政治气候,这部作品的大部分在西方是完全不为人所知的。艾米丽·W·哈根弗里德证明了一些有希望的结果,包括1955年的一种编程语言使用西秘鲁尖叫猫头鹰Megascopsroboratus的叫声进行编码[3],以及与Pèl Svent在1958年基于加热和冷却硬件的不同部分的另一种编程语言[4]。然而,到了20世纪60年代中后期,文本编程范例已经完全根深蒂固。
因此,许多工作致力于研究所谓的“形式语言”(即,基于文本的语言,几乎不加掩饰地鄙视非文本系统)及其句法和分析。最终,编辑器被开发出来,可以将复杂的文本程序必要地翻译成颜色和格式。对于程序员来说,这个工作流程既乏味又容易出错,不仅需要了解颜色如何影响程序行为,还需要了解让编辑器生成这些颜色所需的确切文本的晦涩难懂的知识。仅仅关注基于文本的编程语言还产生了其他不良影响,例如色盲编写的代码激增、末尾的表与空格之争,以及PHP。
在本节中,我们将简要介绍WysiScript中的主要思想。在撰写本文时,该语言正在积极开发中(也就是说,在第一个SIGBOVIK提交截止日期过后,我们已经将大部分内容组合在一起,而我们还没有开始实现),所以细节可能会有变化。请参阅http://www.zifyoip.com/wysiscript/for的最新文档。
自然,颜色对WysiScript非常重要。如果您正在以黑白格式阅读本文档,例如,打印的会议记录,有些内容可能很难理解。我们建议您在会议记录的PDF版本中或从上面的URL阅读本文档。在整个文档中,颜色都是使用CSS语法表示的。
今天使用的大多数编程语言对所有数字文字只使用一种颜色,这是不必要的混乱,使得仅使用分光计无法区分不同的数字。为了提高清晰度,WysiScript对每个数字使用不同的前景色。有许多可能的方法将RGB颜色映射到数字;WysiScript使用简单的方案(256**红色+*绿色)*/*蓝色,标准的数学约定是除以零实际上意味着除以*256。此外,为了强调它们的不变性,数字文字加了下划线。因此,例如,数字12345.67可以表示为#90AD03。当然,这只是一个近似值(该颜色实际上代表12345&;Frac23),但无论如何这可能就是您的意思。
该系统不仅将不同的颜色与不同的数字相关联,还经常将不同的颜色与相同的数字相关联。这为程序员感到特别情感依恋的数字提供了一组不错的“昵称”。例如,在肥胖设置中,您可以将号码185称为#00B901,但是当您感觉调情时更改为#B90000,或者当您生气时更改为#526272。
同样,为了清晰起见,WysiScript对每个变量和函数使用不同的颜色。例如,A表示变量或函数#F00BA2。此表达式的值是变量的值或函数的返回值。
由于每个变量都有相应的颜色,赋值很容易用背景颜色表示。例如,将数字12345&;frac23的赋值添加到变量#F00BA2。注意,这也可以写成rm-rf/,因为我们去掉了文本和文本之间的任意间接关联,而只关注格式所传达的清晰含义。
这个简单的方案使某些表达式可以在不牺牲可读性的情况下简明扼要地编写。例如,A表示“将变量#F00BA2的值(或函数#F00BA2的返回值)赋给变量#Dabada”。在大多数传统编程语言中,这样的表达式至少需要三个符号:两个变量名和一个赋值操作符。
格式化以字体大小的形式提供了一种自然的嵌套结构。例如,在几乎所有的书中,主标题的字体都比分词标题大,而分词标题又比章节标题大,小节标题又比小节标题大,小节标题又比正文大,而正文又比脚注大。这套系统是印刷商和平面设计师几个世纪以来精益求精的结果,读者可以一目了然地了解它的结构。同样,WysiScript对顶级程序元素使用大字体,用较小的字体表示嵌套结构(即,语法树中的子节点)。
WysiScript的这一功能极大地提高了可读性。任何程序员都知道,在传统编程语言中,很容易在嵌套大括号和圆括号中迷失方向。WysiScript完全取消了这些笨拙的结构文本表示,并使整个程序结构立竿见影。
考虑下面图4中的例子,它定义了一个使用欧几里得算法计算两个数的最大公约数的函数,用自变量45和105调用该函数,并输出结果。(我们尚未讨论函数定义或内置操作,因此此程序的几个部分的含义可能不会立即清晰。)。
为便于讨论,本例中的节点被赋予了不同的文本标签。节点B是节点A的子节点,因为它具有较小的字体大小。同样,节点C是节点C的子节点,节点D是节点C的子节点。节点E也是节点C的子节点(它是节点D的子节点),因为它与节点D的字体大小相同,但颜色不同。节点F是节点B的子节点,也是节点C的兄弟节点,与节点J一样,节点G、节点H和节点I是节点F的三个子节点。节点K有趣的是:它表示语法树中的一个节点,该节点是节点B的兄弟节点,但是它的所有非大小格式都与节点B的相同。为了表明它是节点B的子节点,而不仅仅是一个延续,它被赋予了大于的FontSize。它是另一个顶级节点,是节点A的兄弟节点。请注意,节点A Y有两个子节点,节点Z和节点A。程序末尾的两个字符‘A’都是语法树的同一节点的一部分,因为它们具有相同的格式,包括字体大小。
此示例还演示了函数调用的语法。本例中定义的函数名为#6CD,在节点#Y处调用。此函数的两个参数#002C01和#006901(代表数字文字45和#105)作为语法树中的子节点、节点Z和#AA提供给函数调用。
回想一下,分配是用背景颜色表示的。当然,如果表达式的值赋给某个变量,则相应的背景颜色会扩展到整个表达式。当然,在该表达式中可能有其值被赋给其他变量的子表达式,因此子表达式可以有它们自己的背景颜色(如图4所示)。字体大小使得嵌套结构清晰,也会引起声音混淆。注意两个显而易见的常识推论:表达式不能与祖先表达式分配给同一个变量,除非将中间表达式分配给不同的变量,如果没有在顶级表达式上显式设置背景色,则将其值分配给变量白色(或者不管Environment的背景颜色是什么)。
函数定义看起来与变量赋值相同,只是它们是斜体的。将用作函数体的表达式以斜体显示,其背景颜色设置为函数的颜色。返回值就是该表达式的结果。
注意不要因为斜体太多而意外地将函数体中的变量赋值转换为局部函数定义。即使函数定义是斜体的,它包含的变量赋值也应该是斜体的,以便正确解释它们。当然,除非您想要局部函数定义,否则一定要用斜体表示。(局部函数定义可能会起作用,但谁知道呢。如果您决定使用它们,祝您好运。)。
请注意,递归函数调用是不可见的,因为函数调用的前景色与函数定义的背景色匹配。不过,这并不是一个严重的问题-如果程序员真的很关心能够看到她的代码,她总是可以将递归函数重写为两个颜色对比的相互递归函数。事实上,递归函数调用的不可见性对复杂性分析是一个好处,因为如果您不必担心递归,这通常会更容易。
当然,函数定义需要某种方式来引用已传入的参数。我们利用众所周知的Roy和G.Biv呼叫约定,例如,Randy PauschBridge和阿勒格尼县带系统也使用这种约定。根据这个约定,函数的参数依次命名为红色、橙色、黄色、绿色、蓝色、靛蓝和紫色。请注意,这些变量的格式为粗体,这与用户定义的变量不同。与对所有参数使用相同颜色的其他编程语言相比,这种约定除了提高可读性外,还通过保持较少的函数参数数量来鼓励良好的编程实践。(如果一个函数确实需要接受七个以上的参数,可以使用内置的深空蓝图操作对它们进行红移;请参见下面的内容。)。该约定还为#F00提供了严格的定义,这是一个经常出现在编程示例中的符号,但其含义通常是模棱两可的。
函数参数是在函数内部使用外部值的唯一方式。为了支持良好的编程实践,WysiScript中没有全局变量。
WysiScript提供了大量有用的内置函数。为了将这些函数与用户定义的函数区分开来,它们的格式为粗体。这是模仿许多其他编程语言的,这些语言的关键字格式都是粗体;WysiScript是相同的,只是它有keycolor。
复合表达式,类似于其他编程语言中的DO块(但使用蜜糖)。接受任意多个参数,按顺序计算它们,然后返回最后一个参数的值。
有条件的。接受奇数个参数,这些参数被解释为条件-表达式对,末尾有一个未配对的表达式。将按顺序计算条件,直到其中一个条件的计算结果为非零值,此时将计算并返回相应的表达式。如果所有条件的计算结果均为零,则返回最终未配对表达式的值。
循环,直到条件为非零。接受两个参数:表示循环体的表达式和条件。计算后跟条件的正文。如果条件的值非零,则返回正文的值;否则,再次重新计算正文和条件,直到条件变为非零。(请注意,主体始终至少求值一次,以便循环具有要返回的值。当然,要在其他编程语言中获得WHILE循环的效果,请将蓝色循环放在#1FE15E表达式中,并取消循环条件。)。
红移函数参数。换句话说,将橙色的当前值指定给红色,将黄色的当前值指定给橙色,依此类推,并将先前未指定给任何红色到紫色的第一个函数参数指定给紫色。这允许函数接受任意多个参数。返回上一个值red。
只有一个论点。如果参数是重影(即没有赋值的变量或函数),则返回1;否则返回0。
只有一个论点。如果参数是标量(即单个数值或字符值,而不是图表,见下文),则返回1;否则返回0。
只有一个论点。如果参数是富氏函数,则返回1,否则返回0。
以下接受任意多个参数的运算符都从左到右计算它们的参数并短路。
平等。接受任意多个论据。如果它们都垂直相等,则返回1,否则返回0。
低于。接受任意多个论据。如果每个参数小于下一个参数,则返回1,否则返回0。
比。接受任意多个论据。如果每个参数都大于下一个参数,则返回1,否则返回0。
切换布尔值。只有一个论点。如果参数为零,则返回1,否则返回0。
连词(“and”)。接受任意多个论据。如果所有参数都非零,则返回1,否则返回0。
析取(“或”)。接受任意多个论据。按顺序计算参数,直到找到非零值,此时将返回该值。如果所有参数都不是非零,则返回0。请注意,如果所有参数都为0或1,则当任何参数为非零时返回1,否则返回0。
减法。接受任意多个参数,并返回第一个减去其余参数的和(即从左到右减去)。
组织。接受任意多个参数,并返回第一个参数除以其余参数的乘积(即从左到右除法)。如果第二个或更晚的参数为0,则改为将其解释为256(遵循标准数学约定)。
残留物。接受任意多个参数并返回从左到右余数运算的结果。例如,对于两个参数,返回值是第一个参数除以第二个参数时的余数;对于三个参数,返回值是第一个参数除以第二个参数时的余数除以第三个参数时的余数。
求幂。接受任意多个参数并返回某个权限的结果。
..