SumireHina Ri0n72Y Code Farmer, Idea/Trash Creator

计算机科学的基本问题(2)红烧肉的制作过程

» 开发

如果你对红烧肉还有记忆的话,这是它的数据结构:

厨房:{
    厨具:{
        锅:一口好锅,
        刀:一把切肉刀,
        砧板:一块砧板,
        菜铲子:一个炒菜铲,
        盘子:一个盘子
    }
    设备:{
        灶:一个带开关的燃气灶,
        抽油烟机:一台抽油烟机,
        水池:一个水池附带水龙头和下水系统,
    }
    材料:{
        肉:一块上好的五花肉,
        水:一壶水,
        盐:一盒盐,
        糖:一盒糖,
        料酒:一瓶料酒,
        酱油:一瓶酱油,
    }
    厨师:一个很能干的厨师
}

应当注意到的是,只有冒号最右边的东西才是真正有意义的,实际存在的东西。冒号左边的层级则是我们为了自己方便,创造出来用于归类他们的东西。右边我们称之为 data, 左边我们一般称之为 索引 index,或者 变量 variable

如果你之前有接触过计算机编程相关的学习,他们大概会这么告诉你:变量是一个盒子,用来装里面的数据,盒子里的数据可以随意更换,而数据也可以装在合适的盒子里。

这是一个相当容易理解的讲法,但也确实祸害了不少人(包括我)。错误的把盒子当作实体,诞生了大量的全局变量和令人眼花缭乱的写法。

TIPS: 盒子的概念起源于强类型语言的声明语言文件,于当年的 Pascal, C, 和 Ada 中十分流行。就像你准备设置一个图书馆的时候,需要在见到图书之前就准备好书架,最好给每个书架分好类,准备好索引,再去把到来的图书一个一个填进去。这十分易于理解,也符合计算机工学的结构:寄存器,内存就是这样一个一个的小盒子,数据总要放在这些盒子里面。但这个概念却在程序算法设计逐渐复杂且壮大的今天,稍微显得有些不太合适。如果只是论证为何不合适的话,也许我们需要单独开一个系列来搞,这里不多赘述。

我们设计程序,面对的始终都是右侧的数据。无论我们怎么称呼他们,他们都不会表现出不同。无论你给厨师取名为 厨师.厨师.厨师,或者是 GeniusCook, 厨师仍只能执行他能做的工作。变量只是我们对数据的一个代称,程序根据当前的数据生成一组新的数据,交给下面的程序执行,最终得到我们想要的数据。程序设计应当是面对数据搭建的流水线。

在新的 Javascript ES6 中,官方推荐大家使用 const 取代 var。const 的块级作用域和不可变性使得程序减少了很多变量变化中产生的错误,也使得程序设计变得更加严谨了起来。

当然,如果上面的部分没有看懂,那么这里我们就使用易于理解的数学语言来解释。

我们所知道的最简单的函数,高中一般写作 y = ax + b,也可以写作 f(x) = ax + b 其中 x, y 我们称之为未知数。在这里未知数等同于变量,即我们知道这个东西的类型和可以执行的运算,但却不知道准确的值。我们事先定义了函数的运算方法,这样一旦我们有了x,y或者f(x)的值我们也就得到了。

所谓程序设计,本质上就是设计函数算式的右半部分,设计这样一种自动化的流程,依据输入的 x 得到我们想要的 f(x)。如果拿出红烧肉的模型,我们的函数就变成了这个样子:

f(x) = 厨房.厨师.切(x)

当x是肉的时候,f(x) = 切好的肉。但一个很能干的厨师不止会切肉,我们如何定义 切(x) 这个函数呢?

切(x) = 
    If (x == 一块肉) Then 
        厨师.使用(厨具.刀, 厨具.砧板);
        Return 切好的肉;
    If (x == 一个番茄) Then 
        厨师.使用(厨具.刀, 厨具.砧板);
        Return 切好的番茄;
    If (x == 一个土豆) Then 
        厨师.使用(厨具.刀, 厨具.砧板);
        Return 切好的土豆;
    (以下省略)

符号 == 是比较符号,用于比较等号两边的值是否相等,相等返回 true, 不相等返回 false。与 = 不同的是,等号是一个赋值运算符,让等号左边的符号可以去指代右边的值。

条件语句 If (condition) Then {expressions} [Else [If (condition)]] 是条件判断语句,组成编程基础逻辑的三大元素之一。当 conditiontrue 的时候,Then 后面的语句 expressions 会被依次执行。如果 conditionfalse,Else 后面的语句会被执行,两者只会执行其一。很多时候 If 语句会省略掉 Else 部分,表示如果 conditionfalse,则什么都不做。

标准语言表示方法,就是上面描述条件语句的看上去不像人话的句子。condition, expressions 是变量,用于表示一切符合其定义的值。condition 是 boolean 类型,expressions 则代表一句或多句可执行的语句(例如赋值语句或者 If 语句本身,对,它是可以嵌套他自己的)。方括号 [] 则代表了其中的部分是可选的,可以写也可以不写。

Return 代表结束当前函数的运算,将 Return 后面的东西作为该函数的结果返回,它不但可以是一个具体的值,也可以是一个对象或者其他函数,这点我们会在之后的文章里讨论。

我们的厨师非常能干,他除了会 切(x) 这个技能以外,还会很多东西,比如 炒(x) 煎炸(x) 调味(x) 装盘(x) 洗碗() 刷锅() 等等不同的技能。这样整个厨房都可以交给他来管理,最终做出一份美味的红烧肉。