贴吧惯例,一楼祭天,二楼开始正文。
第一章:定义
1.1:为什么我们需要定义?
1.1.1:替换式定义
有这样一个经典的问题:
把大象装进冰箱需要几步?
三步。
第一步,打开冰箱门。
第二步,把大象放进去。
第三步,把冰箱门关上。
现在来定义:
定义操作【编号01】:
第一步,打开冰箱门。
第二步,把大象放进去。
第三步,把冰箱门关上。
此时,把大象装进冰箱需要几步?只需要一步:执行编号01的操作。
1.1.2:抽象定义
把老虎装进冰箱需要几步?三步。
如果要想只用一步,那么就需要定义编号02的操作。
但是你会发现,编号02与编号01的操作很像。因此我们可以定义一个抽象的操作:
定义操作【编号03】,参数为【物体X】:
第一步,打开冰箱门。
第二步,把物体X放进去。
第三步,把冰箱门关上。
此时,把老虎装进冰箱需要一步:执行编号03的操作、参数为老虎。
并且,未来把任何东西装进冰箱,都只需要一步,不需要再定义新的操作。
1.2:名词的定义
定义,是【当你想要实现功能X、这需要引入一个概念Y;但计算机中没有概念Y】时,你来定义Y。
例如,当你想说【向集合A中添加一个元素】的时候,你发现计算机中没有集合,只有【低级集合】:这个低级集合的元素数量是固定的,无法改变。
此时,你需要定义【集合】:
定义集合:
定义属性【本体(类型为低级集合)】
定义属性【元素数量(类型为数字)】
定义动词【创建集合】,无参数:本体是一个空的低级集合,元素数量是0。
定义动词【添加元素】,参数为元素X:
创建一个新的低级集合,元素数量是“自身的元素数量+1”。
把本体的元素挨个复制到新的低级集合中。
把新的低级集合的最后一个元素设置为X。
抛弃旧的本体。把这个新的低级集合作为本体。
这样你就可以创建集合并添加元素了。
1.2.*:问答
问:名词的【属性】是什么东西?
答:假设有A与B两个集合。AB不同,为什么他们都叫集合?因为AB的不同只在于【本体】不同或【元素数量】不同。一个名词的有些东西是可以变的。那些可以变的东西就被称为属性。
1.3:代码逻辑的优美
如何描述QQ中的消息发送界面?
如果点击发送,那么在消息记录的右侧添加一条消息。
如果点击发送,那么让消息记录整体上移,然后在消息记录下方的右侧添加一条消息。
如果点击发送,那么:
消息记录整体上移。
设A=输入框中的内容。
在消息记录下方的右侧添加一条消息,内容为A。
现在还有一个问题:跟你聊天的那个人的消息记录也需要修改。
如果点击发送,那么:
消息记录整体上移。
设A=输入框中的内容。
在消息记录下方的右侧添加一条消息,内容为A。
接收者的消息记录整体上移。
在接收者的消息记录下方的左侧添加一条消息,内容为A。
这样的设计不优美。这个设计可以重构成另一种优美的设计:
有一个【公共消息记录】。
公共消息记录中,所有消息都排列在左侧,而非【一人在左,一人在右】。
显示消息记录时:
第一步,生成一个【超高的此人视角消息记录】。
这个消息记录中,此人的消息在右、对方的消息在左。但是没有滚动条。
整个消息记录是一个超高的画布。
第二步,截取这个【超高的此人视角消息记录】的下方区域,显示在QQ的消息记录窗口中。
如果点击发送:
在【公共消息记录】中添加一条消息。
让双方重新显示消息记录。
1.4:面向过程
1.4.1:构建与解释
编程要求构建,而不是解释。
构建:第一步,创造一个空集。第二步,在空集中加入元素【1】。
解释:有一个集合,这个集合有一个元素:【1】。
1.3中有这样一段话:
生成一个【超高的此人视角消息记录】。
这个消息记录中,此人的消息在右、对方的消息在左。但是没有滚动条。
整个消息记录是一个超高的画布。
这段话应当改为:
生成一个空画布。
在这个画布中添加一些消息。此人的消息被放在右侧、对方的消息被放在左侧。
1.4.2:循环
生成一个空画布。
在这个画布中添加一些消息:
从【公共消息记录】中获取所有消息。
对于每一条消息:如果这条消息属于此人,那么把它放在空画布的右侧。否则放在左侧。
生成一个空画布。
在这个画布中添加一些消息:
从【公共消息记录】中获取所有消息。设一共n条消息。
首先看第一条消息:如果这条消息属于此人,那么把它放在空画布的右侧。否则放在左侧。
然后看第二条消息:如果这条消息属于此人,那么把它放在空画布的右侧。否则放在左侧。
然后看第三条消息:……
以此类推,直到看完n条消息。
生成一个空画布。
在这个画布中添加一些消息:
从【公共消息记录】中获取所有消息。设一共n条消息。
设x=1。
看第x条消息:如果这条消息属于此人,那么把它放在空画布的右侧。否则放在左侧。
如果x小于n,那么x增加1、然后回到上一句话。否则结束。
面向过程,是指【从开始,经过过程,得到结果】。
面向结果,是指【解释结果是什么样的】。
【新画布与公共消息记录中的信息一样】,这是面向结果的描述。
【获取公共消息记录中的信息。先处理第一条,再处理第二条……】,这是面向过程的描述。
1.5:定义的技巧——分步定义
1.5.1:找最小值
现在有一串数字:5,7,6,2,9。需要你定义一个动词:排序。这个动词以一串数字为参数,输出这串数字从小到大排序的结果。
你可能没有头绪。
现在我换一个问题:还是这串数字。现在你需要定义一个动词:找最小值。
这个问题就简单了:
先假设第一个数字是最小值。
然后看第二个数字,如果它更小,那么就让第二个数字是最小值;否则,第一个数字就是最小值。
然后看第三个数字……
以此类推,直至看完所有数字。此时的最小值就是真正的最小值。
定义完【找最小值】之后,再看原本的问题:定义排序。此时就不难了:
先找到最小值。把它写在第一位。
然后看剩余数字,找它们的最小值,把它写在第二位。
然后看剩余数字,找它们的最小值……
以此类推。直至看完所有数字。
1.5.2:滚动条
滚动条怎么定义?
你可能没有头绪。
现在我问你:滚动条的本质是什么?
这个问题很简单:
滚动条的本质,就是【一个物体移动,另一个物体会跟着移动】。
现在回到原本的问题:滚动条的定义。此时就不难了:
有一个滚动块,一个滚动区域,一个被滚动区域。
如果滚动块向上移动,那么被滚动区域向下移动。反之亦然。
滚动块只可以上下移动(不可以左右移动)。
1.6:语句
一句话的基本结构是什么?主谓宾?
不。
自然语言中之所以通常是主谓宾结构,是因为自然语言是一维的,动词左右各可以连接一个名词。但真正的语句中,名词可以只有一个,也可以有三个四个。
古人的解决办法是:对于只有一个名词的,创造一个新名词。对于有多个名词的,拆分出多个谓词。
比如,自然数公理【0是自然数】,这句话的严谨描述是【P(0)】,其中P是一个谓词、相当于【是自然数】。这就是一个【只有一个名词的语句】。
注:有的人觉得不严谨,觉得这不是一个语句,觉得【0属于自然数集】这样的描述才是严谨的语句。但是,什么是集合?他可能回答:空集是集合,一个集合可以构造一个幂集,两个集合可以并。但是,你打算如何严谨描述【空集是集合】?你要描述为【空集属于全部集合所构成的集合】吗?你这是循环定义了。只能说【Q(空集)】,此处的Q相当于【是集合】,这就是一个只有一个名词的语句。
三四个名词的语句很常见,比如【画一个宽为5、高为4的红色矩形】,这本质是【画矩形(5,4,红色)】。再比如【我认为你能做到某事】,这本质是【认为能做到(我,你,某事)】,进一步可以写成【P(我,你,某事)】,P是一个新谓词。
1.6.*:总结
一句话的基本结构,是谓语+参数。谓语只有一个,参数可以有任意个。
自然语言是一维的,这导致谓语强行绑定两个参数。不要被自然语言束缚了思维。