当前位置: 首页 > 科技观察

如果你来发明一门编程语言

时间:2023-03-17 19:05:24 科技观察

,聪明的人类发现组合简单的开关可以表达复杂的bool逻辑,并在此基础上构建CPU,所以CPU只能简单理解开关,开关用数字表示为0和1.创世记:聪明笨的CPU相当原始,就像一个单细胞生物,它只能把数据从一个地方移动到另一个地方,简单的相加,没有任何高难度的动作,虽然这些操作看似简单笨拙,但是CPU有一个无可比拟的优势,那就是一个字:快,这是人类无法比拟的。CPU出现后,人类开始有了第二大脑。这就是一种原始物种如何开始支配另一种称为程序员的物种。一般来说,如果两个不同的物种想要交流,比如人和鸟,有两种方式:要么鸟说人类的语言,人能听懂;要么鸟说人类的语言,人能听懂;或人说鸟语,让鸟听懂;这取决于谁是好人。一开始,CPU赢了。程序员们开始说鸟语,认真感受CPU的霸权,让CPU高手干活。感受一下第一位程序员怎么说鸟语:程序员直接用0和1写指令,你没看错,这狗屎就是代码,太原始了,然后放到打孔纸带上输入到CPU,CPU开始工作了,这时候的程序真的可以看得见摸得着了,有点浪费纸。这时候程序员就必须站在CPU的角度来写代码了。画风是这样的:1101101010011010100100110010100111001000110111101011101101010010乍一看,你知道这是什么意思吗?知道了这一点,我想“这简直是世界上最美丽的语言”。天降大使命终于有一天,程序员们受够了说鸟语,至少他们是灵长类动物。用鸟语叽叽喳喳太丢人了,你被委以重任:让程序员说人话。你没有努力,而是仔细研究了CPU,发现CPU执行的指令集只是来来回回的几条指令,比如加法指令、跳转指令等,于是你将机器指令与相应的机器指令进行比较那些。具体操作做了一个简单的映射,将机器指令映射为人类可以理解的单词,这样上面01的字符串就变成了:sub$8,%rspmov$.LC0,%edcallputsmov$0,%eax,程序员们不用记住1011...但只需记住人类可以识别的单词,例如ADDSUBMULDIV。于是诞生了汇编语言,这是人类能够理解的第一种编程语言。这时候,程序员终于不再需要“twitter...”,而是升级为“Abaaaba...”,虽然人类认识“Abaaaba”这个词,但它与人类语言在形式上的区别还是有的有点大细节与抽象汇编语言和机器语言一样,是一种低级语言,尽管它已经有了人类可以识别的词。所谓低级语言,就是你需要关心所有的细节。你关心哪些细节?正如我们所说,CPU是一个非常原始的东西。它只知道如何将数据从一个地方移动到另一个地方,然后通过简单的操作将数据从一个地方移动到另一个地方。因此,如果要用低级语言编程,就需要使用“将数据从一个地方移动到另一个地方,执行一个简单的操作然后从一个地方移动到另一个地方”等多条简单的指令来实现诸如排序这样复杂的问题。可能有些同学对此感受不深。这就好比,本来你想表达“gobringmeaglassofwater”:如果你用汇编之类的低级语言,你要这样实现:我想你已经到了。弥补差异CPU太简单了,太简单了,任何稍微抽象一点的东西都看不懂,比如“给我来杯水”,但是人类天生就习惯于抽象的表达方式。有没有办法弥合人与机器之间的鸿沟?换句话说,有没有一种方法可以将人类的抽象表达自动转换成CPU可以理解的具体实现,这显然可以大大提高程序员的生产力。现在,这个问题需要你来解决。例行公事,都是例行公事。想一想,你不知道如何自动将人类的抽象转化为CPU可以理解的具体实现。就在你快要放弃的时候,你又看了看一堆CPU能看懂的细节:LightningFlint灵光一闪,发现了很多套路,或者说模式。在大多数情况下,CPU执行的指令很简单,像这样:这些是告诉CPU完成一个特定的动作。你给这些直截了当的指令起个名字,我们称它为语句,语句。另外,你也发现了这样一个套路,就是你需要根据某种状态来决定执行哪条指令。这个例程是“如果……那么……否则……就……":if***blablablaelse***blablabla在某些情况下,有些指令需要不断重复,这个套路好像在兜圈子:while***blablabla最后还有很多看起来很相似的指令,比如这里:这些指令是重复的,但是个别细节有差异,把这些差异提取出来,把剩下的指令打包在一起,用一个代码来指定这些指令,如果有名字,就叫做函数。:funcabc:blablabla现在你已经找到了所有的例程://条件转移if***blablablaelse***blablabla//loopwhile***blablabla//functionfuncabc:blablabla这些相对于汇编语言有了质的飞跃,因为这已经很接近人类语言。然后你发现自己面临两个问题:这里的blablabla是什么?如何把上面人类能看懂的字符串转换成CPU能看懂的机器指令Space,你想想看,我上面说的大部分代码是一个简单的陈述,陈述,这里的blablabla只是一堆陈述吗?显然不是,blablabla可以是语句,当然也可以是条件传递ifelse,或者是循环while或者是函数调用,这是合理的。虽然这是合理的,但你很快就会发现另一个严重的问题:blabalbla可以包含ifelse等语句,ifelse等语句可以包含blablabla,反过来blablabla也可能包含ifelse等语句,ifelse等语句可能包含blablabla,blablabla可能包含ifelse之类的语句...就像盗梦空间一样,一个层层梦中有另一层梦,梦中梦,梦中梦中梦...一层嵌套在另一层中一层,子孙无限稀缺……此时,你已经明显感觉到自己的脑细胞不够用了,这太复杂了,绝望开始吞噬你,天哪,谁能帮帮我!这时候你的高中老师走过来拍拍你的肩膀,递给你一本高中数学课本,你就生气了,你给我这个傻东西干嘛,我想的问题好深奥,怎么办?能不能靠一本破的高中数学书来解,我一把抓起来扔在地上。这时,一阵恶风吹来,教科书停留在这样的一页上,上面有这样一个表达式:f(x)=f(x-1)+f(x-2)这个递归是干嘛的公式快递?f(x)的值取决于f(x-1),f(x-1)的值取决于f(x-2),f(x-2)的值也取决于它。..一层嵌套一层,梦中梦,语句嵌套if,语句可以嵌套if。..等等,这不就是递归吗?上面看似无穷无尽的嵌套也可以用递归来表达!你的数学老师仰天大笑,太年轻太简单了,让你丢脸走人,貌似高科技的东西,我要解决的事情,用高中数学就解决了,愣了一下,还有我不知所措,感到羞愧。在递归概念的加持下,聪明的智商又开始占据制高点。递归:代码的本质不就是一层层嵌套吗,递归就是为了表达这个东西而生的(提示:这里的表达并不完整,真正的编程语言没有那么简单):if:ifboolstatementelsestatementfor:whileboolstatement语句:if|for|statement嵌套在Inception空间之上一层,所以可以用这么简单的几句话来表达。你给这几个句子起了个高端的名字和语法。数学使一切变得如此优雅。世界上所有的代码,无论多么复杂,最终都可以归结为语法。原因很简单。所有代码都以语法形式编写。至此,您已经发明了一种真正的人类可以理解的编程语言。前面提到的第一个问题是解决了,但是光有语言是不够的。计算机理解递归仍然存在问题。我们如何才能最终将这种语言转换成CPU可以理解的机器指令呢?人类可以根据语法编写代码。这些代码实际上是一串字符。计算机如何理解使用递归?用文法表示的一串字符呢?这是事关人类命运的大事,不禁感慨责任重大,但这最后一步似乎很难,不禁仰天长叹,计算机太难了。这时,你的初中老师走过来拍拍你的肩膀,递给你一本初中植物学课本。你生气了就生气了,为什么要给我这个废话?我在想这么高深的问题,怎么会是废初中教材呢?能化解的,一把抓住,扔在地上。这时,又一阵风吹来,书翻到介绍树的章节,看着这一页不禁傻眼:树干下面是树枝,树枝下面是树叶,树枝下面也可以是树枝,树枝下也可以是树枝。如果你吃葡萄,你不会把葡萄皮吐出来。如果你不吃葡萄,你会把葡萄皮吐出来。嗯?,子孙无限荒,高中数学老师,等一下,这也是递归!!!我们可以用一棵树来表示按照递归语法写的代码!,看似高科技的东西,用初中知识就可以解决。一个优秀的翻译者的计算机在处理一种编程语言时,能够按照递归定义将代码组织成树的形式。由于这棵树是根据语法生成的,所以我们称它为语法树。现在代码以树的形式表示。仔细观察,你会发现叶子节点的表达方式其实很简单,很容易翻译成相应的机器指令。只要将叶子节点翻译成机器指令,就可以把这个结果应用到叶子节点的父节点,父节点可以将翻译结果引用到父节点的父节点,向上传递一层一层,最后可以将整棵树翻译成具体的机器指令。完成这项工作的程序也必须有一个名字。根据“不懂原理”,你给这个类似翻译的程序起一个不太响亮的名字,编译器,编译器。你还认为二叉树等数据结构没有用吗?至此,你已经完成了一项了不起的发明。程序员可以使用人类已知的东西来编写代码。你写的一个叫做编译器的程序负责把它翻译成CPU可以理解的机器指令。后人根据你的想法构建了C/C++,以及后来的Java和Python。仍然有很多人在使用这些语言。总结一下,世界上所有的编程语言都是按照特定的语法编写的。编译器根据语言的语法将代码解析成语法树,遍历语法树生成机器指令(C/C++)或字节码(Java),然后交给CPU(或虚拟机)执行。因此,高级语言的抽象表达能力非常强,其代价是牺牲了对底层的控制能力,这也是为什么操作系统的一部分需要用汇编语言编写的原因。汇编语言对底层细节的强大控制是高级语言无法替代的。最后请注意,本文牺牲了严谨性来换取对编程语言的通俗易懂的解释。这里的语法不体现函数、表达式等,真实语言的语法远比这里复杂。另外,编译器不会直接将语法树翻译成机器语言,而是生成一种类似于机器指令的中间语言。经过一系列复杂的优化,最终生成真机指令。真正的编译器远比这复杂。我希望本文能帮助您理解编程语言。