我们经常说程序只是指令列表,但这并不能说明这个看似简单的想法的复杂性。 程序的思想不存在于任何特定的编程语言之内,但只有在程序被表达出来后,我们才能看到并体验它。 这就很难将基本思想与语言功能区分开来。

你可能会认为编程是随着计算机一起发明的,但其实不是这样的 – 编程可以追溯到更久远以前,实际上根本不依赖于数字计算机的概念。

毕竟,程序只是指令列表,这个想法与写作本身的历史一样古老。

谁知道呢,也许发明书面交流是为了使我们编程和交流程序思想,但是无论如何,事实上的编程远远早于巴贝奇的思想。

让我们在没有任何先入之见的情况下看看程序的基本概念。

顺序法则

鉴于程序只是指令列表,您可能会认为我们对此做的所有小题大作都有点不合理的。然而,这是低估了这个看似简单的想法的复杂性。

指令列表确实很简单。编程要做的就是写下每个步骤要完成的工作。

例如,告诉你如何建造飞机模型的说明书就是一个程序。遵循说明书,从第一步开始,然后继续进行第二步。第二步完成后,请继续执行第三步,依此类推。

程序所使用的语言通常比标准英语要精确一点,但它并没有什么特别之处 - 在大多数情况下,通常可以做到更精确,但这是另一种类型的问题。

指令是程序,模型构建器是计算机,你甚至可以将实际模型本身视为程序处理的数据。

程序员使用什么做编程(程序员应知系列)(1)

人类计算机

在嘲笑这样一个简单的想法过于简单之前,你需要意识到有些人无法遵循指令列表 - 他们只是不能理解顺序的思想。它们被扁平包装家具的组装表所困扰,不知道该怎么办。一个天生的程序员接管这些指令,并一个接一个地遵循它们,意识到这是完成任务的唯一途径。

程序员接受顺序指令的法则,并且不允许在程序之外进行任何操作。

当然,像Windows和Linux这样的伟大程序,不可能仅仅是在飞机模型套件中找到的那种说明列表?!

顺序指令可以让你走到这里,但并非全部。要了解程序的完整概念,还需要一些其他重要思想。

当将两个关键思想(条件和循环)添加到基本指令列表中时,编程就会开始变得更加复杂。

可以说,这两者都是“指令列表”更基本发展的产物——自我引用的能力。当一个指令列表包含指向该列表本身的指令时,神奇的事情就会发生,条件语句和循环都只是自我引用的例子——但这让事情保持简单。

条件指令

条件指令是这样的指令: 如果你想把飞机模型挂在天花板上,就把Z部分粘到机身上。

程序员使用什么做编程(程序员应知系列)(2)

你想把它挂在天花板上吗?

所有这些都很简单,你可以看到一般情况下这种条件式是这样的:

IF condition THEN DO instruction(IF 条件 则 做指令)

这不仅是一种易于理解的自然语言,而且与几乎所有编程语言都非常接近。

例如,在Visual Basic中你可以这样写:

IF a=0 THEN beep

而在Python中,你不可能更简洁地编写相同的内容,如下所示:

if a= = 0:

beep

关键是,所有的编程语言都有这种条件,只有微小的细节不同。

下一个问题是,条件能有多复杂? 我们是否需要发明各种不同类型的条件指令来构建程序?

答案是否定的!

事实证明,这个简单的IF...THEN...就是你编写任何程序所需要的。

它是一种原子构造块,可以从中构造所有其他类型的条件。

例如,一个稍微复杂一点的条件是:

IF condition THEN instruction A

ELSE instruction B

在这种情况下,我们要么执行指令A,要么执行指令B,这取决于条件是真还是假。

例如: 如果你想把飞机模型挂在天花板上,就把Z部分贴在机身上,否则就把Z部分贴在机翼上。

你可以看到是这样的:

IF hang model THEN stick Z to body

ELSE stick Z to wing

(如果悬挂模型,就将Z粘到身体上,否则将Z贴在机翼上)

你也可以看到这样写:

IF hang model THEN stick Z to body

IF not hang model THEN stick Z to wing

(如果悬挂模型,就将Z粘到身体上;如果不挂模型,则将Z粘在机翼上)

因此一个IF…THEN…ELSE可以转换为两个IF...THEN。请注意,这种转换实际上比你想象的要复杂,在实践中,你必须非常小心,不要词不达意。

正如在程序中“词不达意”被称为bug一样,因此大多数编程语言的确提供了条件式的IF...THEN...ELSE形式以及其他一些常用的形式。但是请记住,在实践中需要这些,而从理论上讲则不需要。

理论上,你需要的唯一条件语句是IF...THEN形式。如果你思考一下在做不同事情之间做出选择的条件,以及如何通过使用多个IF...THEN指令来实现这一点,你就会明白为什么会这样。

IF...THEN提供了一个切换到可选指令集的开关。使用多重切换,您可以在尽可能多的可选列表中进行选择。

循环

条件语句相当容易理解,循环也是如此,但它还有其他意想不到的地方。

在很多方面,正是这种循环让程序变得非常神奇,几乎赋予了它们自己的生命。

一个循环只是指令列表的一个重复部分。

例如:

repaint the fuselage until it is smooth enough(重新油机身,直到它足够光滑)

在自然语言中,我们倾向于隐藏重复,就好像我们对此感到羞耻一样 - 也许我们就是这样的!

一个更精确的重绘指令版本应该是这样的:

REPEAT the paint instruction until the result is smooth enough(重复涂漆指令 ,到结果足够顺利)

这个表单更清楚地表明,您确实被要求重复说明列表中的一部分——“绘制模型”,直到满足某些条件为止。

在编程语言中,通过编写类似以下内容来使重复更加清晰:

REPEAT

Actions to be repeated

UNTIL condition

(重复

需要重复的动作

直到条件)

您可以将REPEAT和UNTIL视为标记了将要重复的列表部分。

出于某些原因,这种“括号”对于初学者来说很难。他们似乎觉得很难读懂一个程序并确切地查到正在重复的是什么。他们似乎对将文本翻译成要做的内容的方式非常模糊。如果你是一个经验丰富的程序员,你会发现这难以置信,因为您很自然地阅读该循环并了解它在“执行”方面的含义。可以按照自己的指示操作,然后到达UNTIL时,您会根据情况非常清楚地知道会发生什么。您可以继续执行其他操作或“返回”并再次执行操作。初学者对条件到底是什么以及程序返回的确切位置感到非常困惑。

理解循环是成为程序员必须克服的障碍之一。

为什么循环如此特殊?

没有循环,你的程序只有跟它包含的指令数目一样多。通过循环,程序不需要那么长就可以一直运行!

例如,一个永远需要完成的程序是:

REPEAT

BEEP

UNTIL forever

(重复

哔哔的声音

直到永远)

它只会发出哔哔声——永远。

如果没有循环,程序将会运行一个固定的非常短的时间,并且无法处理重复的事件,比如你按下键盘上的键。

下一个问题是需要多少种类型的循环? 也就是说,如果只有一个条件指令(IF...THEN),那有多少种不同类型的循环呢?

鉴于循环是那么复杂,你会惊讶地发现你只需要一种类型,而不是REPEAT..UNTIL形式!

原因不难看出,如果你问自己“REPEAT...UNTIL”这个词能重复多少次。由于重复指令列表的测试只出现在最后,你应该能够计算出它被执行的最少次数是一次。

这是一个REPEAT...UNTIL循环,它会重复一个指令列表一次或多次。为什么这还不足以成为一种普遍的重复?

答案是,你可能想要一个有时根本不执行的指令列表!例如,

喷漆模型,到你满意为止

意味着你至少得喷漆一次。它不允许这样的事实:你可能会喜欢它没有油漆!

大多数编程语言通过引入while循环来解决这个问题

WHILE condition

Actions to be repeated

END WHILE

(当 条件 满足时

执行需要重复的动作

结束)

在本例中,在执行操作之前测试条件,如果条件为假,则完全跳过循环——即循环可能在正确开始之前就停止了。

初学者觉得while循环很难。他们发现使循环继续而不是停止的方式很难处理。大多数时候,我们会一直想着做某件事,直到完成——例如,搅拌咖啡直到糖溶解。我们不擅长为继续循环设置条件 - 例如,当你可以看到糖在搅拌的咖啡中。前者很自然,而后者则显得挑剔而笨拙。(如果你不同意,那么很可能你已经当了一段时间的程序员了!)

While的第二个问题是,如果条件已经为真,初学者很难在一开始跳过指令。这就好像他们是在While条件下看到文本,被迫阅读它,并遵循通常的顺序法则。这种情况在IF...THEN中会发生,但WHILE似乎确实是个大问题。

重点是while是一个可以执行零次或多次的循环。

这使得WHILE循环比UNTIL循环更强大一些,但老实说,它们都很有用,并且一点点思考就可以把WHILE循环写成IF和UNTIL的组合:

IF condition THENREPEAT actions UNTIL condition

(如果 条件成立

重复 动作 直到 条件成立)

如果你不太明白,也不要太担心。

重要的一点是,您决定将特定类型的循环视为一个必须执行一次的循环是有点武断的。

同样,与条件语句一样,重要的一点是,只需要一种循环类型即可编写任何程序。也就是说,使用IF. THEN和WHILE循环,可以编写任何使用更复杂命令的程序。

结构化程序设计

这是1960年代编程革命的基本发现——结构化编程——过去几十年来的困惑被它的简单性所取代。

结构化编程将Spartan(斯巴达)规范引入了编程,这种编程试图将使用各种条件和循环构造的杂乱复杂程序更改为易于阅读的文本,只在其中使用一种条件和一种或两种其他类型的循环。

从今天的角度来看,仍然是令人惊讶的,限制程序员使用的指令范围之类的简单操作能够被认为是革命性的,并且可以解决创建更好的程序的问题!

它具有革命性的事实更多地表明了我们以前编程的方式是多么原始。

计算机被发明后,像约翰尼·冯·诺依曼(Johnny Von Neumann)这样的人才能够就如何构建它们写了数学上优雅的理论。另一方面,编程不是发明出来的,它只是发生了而已!过了一段时间,人们才意识到我们需要编程理论——我们现在仍然需要。

回顾“结构化编程”时代,我们会百感交集。

在那个时代,程序员被赋予了一套相当随意的规则,并被告知这是正确编程的唯一方法。

今天,我们知道编写好的程序有很多方法,更重要的是认识到好的程序是易于理解的程序。如果他们希望能够修复和扩展程序,就不仅需要能够阅读并执行该程序的计算机,还必须阅读并理解该程序的其他程序员。这种必须将程序设计为由计算机执行并由人类阅读的想法,可能是迄今为止编程理论上最重要的一步!是的,甚至比对象或函数式编程还要重要的多。

真正的编程语言通常有一系列不同类型的循环结构,只是为了使编程更容易。例如,Visual Basic具有

DO WHILE condition

Actions to be repeated

LOOP

(当 条件成立 时做

重复动作

继续循环)

DO

Actions to be repeated

LOOP UNTIL condition

(做

重复动作

循环直到条件成立)

实际上,许多现代语言都采用了循环构造并将可自由使用。

循环的唯一不同之处在于它们的“退出”点(即停止循环的指令)的位置。WHILE循环的退出点在循环的最开始,REPEAT循环的退出点在循环的最末尾。在Visual Basic和许多其他语言中,你可以同时拥有这两个循环,并且可以在循环中的任何位置都有一个退出点

DO

Actions to be repeated 1

IF condition THEN EXIT DO

Actions to be repeated 2

LOOP

(做

重复动作1

如果条件成立,然后退出循环

重复动作2

继续循环)

现在,退出之前的重复动作列表将至少执行一次,但是退出之后的动作列表可能根本不会执行 - 这是WHILE和UNTIL之间的一种交叉。

在结构化编程的黑暗时代,这样的结构可能是异端邪说,但现在我们知道得更多,思想也更开阔了……

编程就是将静态指令文本转换成一系列以特定顺序发生的动作。

这种从文本到序列的映射,这是编程的本质。

,