多年来,我一直在用多种语言编程,我经常发现自己在用英语伪代码思考,然后我把我的想法翻译成我当时使用的任何人工语法。所以有一天我想,“为什么不简单地在自然语言级别编写代码,跳过翻译步骤呢?”我的大儿子(也是一名程序员)和我讨论了这个问题,我们决定测试这个理论。具体来说,我们想知道:
1.当你不必将你的自然语言思想翻译成另一种语法时,编程是否更容易?
2.自然语言能否以相对“草率”的方式进行解析(就像人类解析自然语言一样),并为高效编程提供足够稳定的环境?
3.低级程序(如编译器)能否方便高效地用高级语言(如英语)编写?
因此,为了回答这些问题,我们开始开发一个简单的英语编译器(用简单的英语)。我们很高兴地报告,我们现在可以从直接经验中回答这三个问题中的每一个,并响亮地说:“是的!”
理论
我们相信,我们的解析器的运作方式与人脑中的解析中心类似。比如说,一个父亲对他的儿子说…
“Want to suck on this bottle, little guy?”
那孩子听到…
“blah, blah, SUCK, blah, blah, BOTTLE, blah, blah.”
……但他做出了正确的回应,因为他有一个瓶子的“图片”,在他头部的右侧与左侧的“瓶子”一词相连,而在他脖子后面与“吮吸”一词相连的一个预先存在的“技能”换句话说,孩子尽可能地将自己积累的图片(类型)和技能(常规)与之匹配,而忽略其他内容。我们的编译器也做了同样的事情,新的图片(类型)和技能(例程)不是由我们定义的,而是由程序员在编写新的应用程序代码时定义的。
实践
典型的类型定义如下所示:
A polygon is a thing with some vertices.
在内部,名称“多边形”现在与一个动态分配的结构相关联,该结构包含一个双链接的顶点列表。“顶点”在其他地方(在此定义之前或之后)以类似方式定义;复数是自动理解的。
典型的例行程序如下所示:
To append an x coord and a y coord to a polygon:
Create a vertex given the x and the y.
Append the vertex to the polygon’s vertices.
请注意,参数和变量不需要正式名称(专有名词)。我们认为,这是一个重要的见解。现实世界中的椅子或桌子永远不会(在正常对话中)被称为“c”或“myTable”——我们把这些东西简单地称为“椅子”或“桌子”。同样地,“顶点”和“多边形”是这些变量最自然的名称。
还请注意,例程和变量名中允许使用空格(如“x coord”)。令人惊讶的是,并非所有语言都支持此功能;毕竟,这是21世纪。还请注意,也允许使用“昵称”(例如“x”代表“x coord”)。所有格(“多边形的顶点”)以非常自然的方式引用记录中的字段。
还要注意的是,单词“given”可能是“using”或“with”或任何其他等效词,因为我们草率的解析侧重于理解所需的图片(类型)和技能(例程),而尽可能忽略了其余部分。
就像一本数学书
在最底层,情况如下:
To add a number to another number:
Intel $8B85080000008B008B9D0C0000000103.
请注意,在本例中,我们在一个例程中有最高和最低的语言——英语和机器代码(十六进制)。这里的观点是,程序应该主要用自然语言编写,根据需要(并且仅根据需要)使用更合适的语法编写代码片段。就像一本典型的数学书:大部分是自然语言,公式片段穿插其中。
我们希望有一天,这项技术将在高端扩展,包括普通西班牙语、普通法语和普通德语等;在低端,为最有用的领域特定语言提供“片段解析器”。
反对意见得到了答复
现在也许你认为自然语言编程是一个愚蠢的想法。但是你考虑过这样一个事实吗 最 中的代码 最 程序会做一些简单的事情,比如“把这个移到那边”和“在屏幕上显示”——用自然语言最方便、最自然地表达的事情?让我们考虑一个例子,我们可以详细检查:
我们的编译器是一个复杂的从简单英语到可执行机器代码的翻译程序,里面有3050个祈使句。
其中1306条(约42%)是条件语句,其中至少有一半是这样的小事:
If the item is not found, break.
If the compiler's abort flag is set, exit.
这些条件语句的其余部分稍微复杂一些,但它们都可以放在一行中。下面是几个较长的:
If the length is 4, attach $FF32 to the fragment's code; exit.
If the rider's token is any numeric literal, compile the literal given the rider; exit.
在剩余的句子中:
272条(约9%)是简单的赋值语句:
Put the type name into the field's type name.
202(约7%)只是各种环路的基础设施:
Loop.
Get a field from the type's fields.
[ other stuff here]
Repeat.
183(6%)只需在这个或那个列表的末尾添加一些内容,如下所示:
Add the field to the type's fields.
164(约5%)是用于返回布尔结果、启动和停止各种计时器、显示程序当前状态以及将有趣的内容写入编译器输出列表的简单语句。
Say no.
Say yes.
Set the variable's compiled flag.
Start the compiler's timer.
Stop the compiler's timer.
Show status "Compiling...".
List the globals in the compiler's listing.
119(约4%)提高了源代码的重点,如:
Bump the rider.
Move the rider (code rules).
92(约3%)用于创建、销毁和更新内部索引,如:
Create the type index using 7919 for the bucket count.
Index the type given the type's name.
Destroy the type index.
58(约2%)用于在各种列表中查找内容:
Find a variable given the name.
37(约1%)是对各种转换例程的调用:
Convert the rider's token to a ratio.
31(约1%)用于生成实际的机器代码(加上条件语句中出现的代码,如上所述):
Attach $E8 and the address to the fragment.
这占了我们编译器中80%的代码。
剩下的句子中只有57句(不到整个句子的2%)是数学性质的,这里和那里的一行是这样的:
Add 4 to the routine's parameter size.
Subtract the length from the local's offset.
Multiply the type's scale by the base type's scale.
Calculate the length of the field's type.
Round the address up to the nearest multiple of 4096.
其余的都不是公式化的。比如:
Copy the field into another field.
Append the fragment to the current routine's fragments.
Abort with "I was hoping for a definition but all I found was '" then the token.
Initialize the compiler.
Remove any trailing backslashes from the path name.
Reduce the monikette's type to a type for utility use.
Eliminate duplicate nicknames from the type's fields.
Prepend "original " to the term's name.
Extend the name with the rider's token.
Unquote the other string.
Read the source file's path into the source file's buffer.
Generate the literal's name.
Extract a file name from the compiler's abort path.
Write the compiler's exe to the compiler's exe path.
Swap the monikettes with the other monikettes.
Skip any leading noise in the substring.
Scrub the utility index.
Fill the compiler's exe with the null byte given the compiler's exe size.
Position the rider's token on the rider's source.
Pluralize the type's plural name.
Link.
Finalize the compiler.
Check for invalid optional info on the type.
这就是为什么我们这么说 最 什么 最 程序做的事情很简单,可以用自然语言方便地表达。这就是为什么我们喜欢用纯英语编程:我们头脑中的想法被输入为纯英语的“伪代码”,并且,在这里和那里做了一些调整,伪代码实际上是编译和运行的。而且是自我记录,引导。
另一个反对意见得到了答复
你可能认为自然语言对于编程来说太冗长了。但真的有那么糟糕吗?让我们考虑几个例子。在传统编程语言中,我们可能会使用以下语句绘制一个框:
substring.draw ( box, color, source.text.font, source.text.alignment ) ;
其中包括10个单词和11个标点符号:共21个元素。
简单的英语对应词是:
Draw the substring in the box with the color and the source's text's font and alignment.
这是16个单词和3个标点符号:共19个元素。
诚然,简单的英文版本需要几个更容易输入的字母字符(由于传统的编码人员在不同的地方放置空格,很难说确切的数字);但这是不必学习(或思考)人工语法的小代价。
下面是另一个例子:
if ( ! source.colorized ( ) ) color = black ;
其中包括5个单词和8个标点符号:共13个元素。
与普通英语相比:
If the source is not colorized, put black into the color.
这是11个单词和2个标点符号:共13个元素。
同样,这主要是一个问题,你是喜欢键入单词还是(专门的)标点符号。以及你是否喜欢同时以两种不同的句法和语法形式思考。以及您是否希望自己的代码能够自我记录。以及你是否想要对初学者友好的代码。和 你是否想用一种100年后仍然普遍使用的语言(如英语)编写代码 从现在开始。就个人而言,我们认为你可能失去了一些 人类 如果你开始认为“(!source.colorized())”是一种很好的表达方式,那么就要有透视效果!
原型
如果您感兴趣,可以在这里下载整个shebang:
这是一个小的Windows程序,大小不到1兆字节。但它是一个完整的开发环境,包括一个独特的界面、一个简化的文件管理器、一个优雅的文本编辑器、一个方便的十六进制转储程序、一个本机代码生成编译器/链接器,甚至一个wysiwyg页面布局工具(我们用来生成文档)。它完全是用简单的英语写的。源代码(约25000句)包含在下载中。无需安装;拉开拉链。从“documentation”目录中的“instructions.pdf”开始,在你阅读10页之前,你不仅仅是在写“Hello,World!”在屏幕上,您将自己重新编译整个内容(在沃尔玛的底层机器上不到三秒钟)。
谢谢你的时间和兴趣。
泽帕 普通英语程序员奥斯莫斯教团的大内格斯
Dan Rzeppa 普通英语程序员奥斯莫斯顺序的主要汇编程序