[Day 26] 阿嬷都看得懂的程序语言在干嘛

阿嬷都看得懂的程序语言在干嘛

我们都希望能够有个神灯精灵,能够实现我们的所有愿望。然而,我们的愿望最後常常成为猴爪的悲剧。所以英文俗谚才说,「小心许愿,因为它可能实现」。今天就让我们练习怎麽许愿吧!

想像我们有个非常厉害,但也非常耿直的神灯精灵。只要我们下的指令,无论多需要严密计算,或者多需要无聊重复,它都会尽量完成。然而,神灯精灵只能接受最直接的指令,没办法猜测我们的暗示或言外之意。同时,这位神灯精灵的记性也很差,我们没有特别请它记得的事物,它就不会记得;另外,就算我们有请它记得,在完成当前任务以後,它也会立刻忘记。

那麽,我们要怎麽写下我们任务,让神灯精灵能够顺利执行呢?让我们想想,应该怎麽让神灯精灵,帮我们用 1000 元纸钞买杯 40 元的珍珠奶茶呢?

首先,因为我们说过神灯精灵的记性很差,所以它不会记得我们给它多少钱,也不会记得我们要买什麽东西。不过,这个神灯精灵有个好玩的地方:只要我们给事物一个名字,这个神灯精灵就会在执行该次任务的时候,记得那个名字,以及这个名字代表的事物。所以,我们要帮神灯精灵写下:

有个名字 十月五号的钱钱 = 1000
有个名字 十月五号的待购商品 = {品项:"珍珠奶茶",价钱:40}

我们不能只写下 1000,不然神灯精灵会忘记这个 1000 是什麽东西。我们必须告诉神灯精灵说,有个名字叫作「十月五号的钱钱」,这个名字代表 1000 这个数字。我们使用1 个半形等号,将这个名字与代表的东西串连起来。当然,你可以不把名字取叫「钱钱」,可以是「猫猫」、「狗狗」,神灯精灵都会记得。由於这个名字可以随便乱取,也可以代表各种东西,所以我们把这个名字叫作 「变数」(variable)。不过,因为我们这边的任务和钱有关,为了我们自己阅读方便,还是就叫「十月五号的钱钱」吧!

我们把告诉神灯精灵有哪些变数的动作,称作 「宣告」 (declare) 变数。由於我们是使用变数,帮助神灯精灵记得这些事物,这就好像我们把这些事物,存放进神灯精灵的记忆当中一样;因此,我们会说。我们用这些变数来存入 (save) 这些事物。由於我们会告诉神灯精灵,这些变数代表哪些事物,这就好像我们让这些变数指到这些事物一样;因此,我们也会说,我们把这些事物 指定 (assign) 到某个变数。

当我们的变数代表的东西,里面有很多不同的属性,例如上面看到的「品项」、「价钱」的时候,我们会把这个东西叫作 「物件」(object)--毕竟每个物件都有很多不同的属性嘛。我们在告诉神灯精灵,这个东西是个物件的时候,会使用一个花括弧,表示这些属性都属於同个物件,当中的属性则用半形逗号隔开。另外,当我们写下纯文字/文字串 (character/string)的时候,必须前後加上双引号,才能够和告诉神灯精灵的名字区分开来。如果是 数字 (number),就单独出现就可以了,不用加上任何括弧或引号。

然後,我们要告诉神灯精灵怎麽做买东西这件事情:买东西这件事情是这样的,我会跟你说钱钱是多少,也会告诉你待购商品是什麽。然後你会从待购商品中,找到价钱。把钱钱减掉待购商品的价钱後,回覆我钱钱剩下多少。

让我们把上面这段文字用神灯精灵语简写一下。我们会先跟神灯精灵说,

  1. 它现在有个要去执行的功能 (function,或译「函式」),但是由於神灯精灵记性很差,不会记得有这功能,所以我们同样要给一个功能的名字,像这边可以是「买东西」。然後,
  2. 我们会把神灯精灵在执行「买东西」这个功能时,这个功能会涉及的东西,例如钱钱、待购商品,写在圆括弧里。最後,
  3. 我们会把神灯精灵要做的事情,写在花括弧里。至於神灯精灵做完事情後,是否需要
  4. 回覆 (return) 什麽资讯,或者是否回复资讯,就看情况而定。另外,
  5. 当我们谈到物件的属性,例如待购商品的价格时,会在物件後面加个半形句点,在半形句点後再加上属性。因此,我们会写下:
有个功能 买东西(钱钱, 待购商品){
    有个变数  阿嬷主人要的计算结果 = 钱钱 - 待购商品.价钱;
    回覆  阿嬷主人要的计算结果
}

值得注意的是,在计算钱钱减掉待购商品的价钱後,由於神灯精灵的记性很差,所以它根本不会记得这个计算的结果。这也是为什麽在上面的指示中,我们还是必须先给一个变数,也就是「阿嬷主人要的计算结果」(同理,我们可以取任何变数名称都行,例如「算算」或者「结果啦」都可以),然後让这个变数去表示计算的结果,这样神灯精灵才会有办法回覆这个结果。

另外,由於神灯精灵的记性真的很差,所以它在做完任何功能以後,因为任务已经结束了,所以它会直接忘记这个功能里,我们要它记得的事物。在上面的指示中,只要神灯精灵做完买东西这个功能,它就不会记得阿嬷主人的计算结果是什麽东西。因此,当做完买东西*这个功能後,如果我们问神灯精灵,阿嬷主人的计算结果是什麽呢?神灯精灵会完全不知道那是什麽鬼东西喔!

设定好买东西的功能以後,我们只要告诉神灯精灵:我要你执行买东西的功能,对象是十月五号的钱钱十月五号的待购商品,神灯精灵就会回覆我们结果了。用神灯精灵语来简写,看起来会像这样:

买东西(十月五号的钱钱, 十月五号的待购商品)

这时候,神灯精灵就会把十月五号的钱钱,也就是 1000,减掉十月五号的待购商品的价钱,也就是 40,得到 960 以後,用阿嬷主人的计算结果来代表与记得 960 这个结果,并且回覆我们这个阿嬷主人的计算结果,也就是 960。

你会说,只是买个东西也太简单了吧,不用神灯精灵,阿嬷我每天自己在算帐啊!没错,但是如果需要算一百次、一万次呢?阿嬷应该会觉得很崩溃吧!没错,这就是神灯精灵厉害的地方,它可以永不疲倦地执行繁复的计算,而且速度比我们快速,也不会出错。例如,当我们拿到一张待购商品长达 105 项的清单时,我们会怎麽做呢?

首先,我们会先帮神灯精灵记得这张清单。怎麽记得呢?没错,先给这张清单一个名字。给出名字以後,再告诉神灯精灵这张清单中,有哪些待购商品。当然,每个待购商品,都会有品项与价格。在神灯精灵语中,清单是用方括弧来表示,当中的项目用半形逗号隔开。因此,我们会写下:

有个变数 十月五号的待购商品清单 = [ {品项:"珍珠奶茶",价钱:40}, {品项:"椰果奶茶",价钱:35}, {品项:"珍珠红茶",价钱:35}, ..., {品项:"椰果红茶",价钱:25}]

注意,上面的删节号是碍於篇幅,用来表示没写出的 101 项物件,并不是在写下来的时候就长那样喔。

接着,我们可以告诉神灯精灵,我们要有一个结余帐款的功能,这个功能是这样的:我们待购商品清单中有 105 项物件,然後先对钱钱和清单中第 1 项东西执行买东西的功能,再对钱钱和第 2 项东西执行买东西的功能,再对钱钱和第 3 项东西执行买东西的功能...... 再对钱钱和第某项东西执行买东西的功能,再对钱钱和第某项後那项东西执行买东西的功能 ...... 最後对钱钱和第 105 项东西执行买东西的功能,然後回覆最後钱钱剩下多少。

上面这个做法很直觉,但是却有个严重的问题。我们在最前面已经告诉神灯精灵,钱钱 = 1000,所以,如果我们只是一直对钱钱和清单中的东西执行买东西的功能,最後神灯精灵还是只会记得钱钱 = 1000,所以也就会告诉我们钱钱 = 1000。因此,我们必须在每次对钱钱和清单中的东西执行买东西的功能後,就告诉神灯精灵,现在钱钱不是 1000 了,而是执行完买东西的功能後回覆的结果。换句神灯精灵的话说,我们必须每次都把钱钱 = 买东西(钱钱,清单中第某项东西)。

那麽,我们要怎麽告诉神灯精灵,我们要拿清单中的哪项东西呢?很简单,我们会在代表清单的变数後加上方括弧,再在方括弧里面放入数字,来代表那是第几项。值得注意的是,在神灯精灵的文化中,是用 0 起算最开头的东西。因此,待购商品清单中第一项东西,用神灯精灵语来说,就会是

待购商品清单[0]

聪明的阿嬷应该可以想到,那麽,在神灯精灵语中,待购商品清单中第四项东西的价钱,我们就会说

待购商品清单[3].价钱

另外还有个严重的问题:聪明的阿嬷应该看得出来,我在写上面这个做法的时候,其实就是不断复制贴上,实在很不 DRY!所以懒惰聪明的工程师当然会想把重复的部分提取出来。让我们观察一下,上面这个做法哪边重复了呢?其实就是「对钱钱和清单中第 ?? 项东西执行买东西的功能」的地方重复了。那麽,那个 ?? 的部分有没有什麽规律,我们又可以怎麽描述呢?

我们会发现,那个 ?? 就是从 0 开始跳,下次变 1,再来变 2 ...... 再来变 n,再来变 n+1 ......,最後变 104 就结束。换句话说,我们只要指定好开始是几,下次是几,还有最後是几,就可以告诉神灯精灵该怎麽做这个重复的动作。我们会把开始条件、结束条件、下次跳几号的条件放入圆括弧中,并且用半形分号隔开。当然,我们说从 0 开始,神灯精灵是记不住的;所以,我们还是必须给一个变数,来存入这个跳号的数字。因此,这个重复的模式会这样说:

重复做 (有个变数 跳号 = 0; 跳号<105; 跳号 = 跳号 +1)

然後,就像功能的指令一样,我们会把神灯精灵要做的事情写进花括弧里;因此,用神灯精灵语来说,整个结余帐款的功能看起来会像这样:

有个功能  结余帐款(钱钱, 待购商品清单){
	重复做(有个变数 跳号 = 0; 跳号<105; 跳号 = 跳号 +1){
		钱钱 = 买东西(钱钱, 待购商品清单[跳号])
	}
	回覆 钱钱
}

上面的写法已经很棒了,只有最後一个小小的问题:十月五号的待购商品清单是有 105 项没错,可是如果十月六号的清单有 83 项,十月七号有 561 项,那岂非每次都还要重写一次?没关系,神灯精灵语里面,通常可以直接帮我们计算清单的长度。在这边,我们先把清单的长度当成清单这个东西的一个属性;因此,清单的长度会写成:

清单.长度

所以,我们最後可以把结余帐款的功能改写成这样:

有个功能  结余帐款(钱钱, 待购商品清单){
	重复做(有个变数 跳号 = 0; 跳号<清单.长度; 跳号 = 跳号 +1){
		钱钱 = 买东西(钱钱, 待购商品清单[跳号])
	}
	回覆 钱钱
}

最後,只要我们执行

结余帐款(十月五号的钱钱, 十月五号的待购商品清单)

就可以得到十月五号的钱钱减掉十月五号的待购商品清单每个东西的价格後,得到的结余罗!

这个重复做的模式,有个炫炮的名称,叫作 「回圈」(loop)

嗯嗯,看来神灯精灵还是挺好用的。不过,就在阿嬷们额手称庆的时候,突然传来一个作为阿嬷会很爽,但是作为工程师会很干的喜讯/ 噩耗:饮料店老板年中大放送啦!只要价格 > 30 的东西,全部都算 30 就好了!这时候,我们应该怎麽跟神灯精灵说呢?

直觉地,我们应该会说,那就在重复做买东西这个功能的时候,做个判断就好啦!如果清单中的这项东西的价格 > 30,我们就执行买东西(钱钱, 30);否则,就执行原本的钱钱 = 买东西(钱钱, 待购商品清单[跳号]) 就行了。

没错,因此,在这个状况中,我们会把要做判断的条件放进圆括弧中,然後把符合条件後要做的事情,放进花括弧中。因此,在这个跳楼大特价的情境下,我们给予神灯精灵的指示看起来会像这样:

有个功能  结余帐款(钱钱, 待购商品清单){
	重复做(有个变数 跳号 = 0; 跳号<清单.长度; 跳号 = 跳号 +1){
		如果(待购商品清单[跳号]>30){
			钱钱 = 钱钱 - 30
		} 否则 {
			钱钱 = 买东西(钱钱, 待购商品清单[跳号])
		}
	}
	回覆 钱钱
}

问题来了,我们要判断大於、小於都不会是问题,那我们要判断等於怎麽办呢?因为等於符号已经被我们拿去做变数宣告了啊!!没关系,一个等於符号不够,你有用第二个吗?没错,我们判断是否相等的方式,就是使用** 2 个等於符号**。例如,当我们要判断某项商品的价格是否等於 30
时,就会写下:

待购商品清单[跳号]==30

值得注意的是,我们可以当作判断条件的事情,一定都是我们可以回答「对」(True) 或「错」 (False) 的。例如,十月五号的待购商品清单中第 0 个品项的价格是 40,那麽,十月五号的待购商品清单中第 0 个品项的价格 > 30 吗?答案是「对」。十月五号的待购商品清单中最後一个品项的价格是 25,那麽,十月五号的待购商品清单中第 0 个品项的价格 > 30 吗?答案是「错」。因此,「待购商品清单[跳号]>30」这件事情,才能够当作判断的条件。

这些我们可以回答「对」或「错」的事情,我们说它们具备真假值,也叫作「布林值」(boolean)。真假值和前面我们提到的东西都不太一样。前面我们提过数字、提过文字串、提过物件,也提过清单。这些东西的类别,我们称作「型别」(type)。

根据上述讨论,我们可以发现,型别会影响运算的方式。因此,各型别间也有各自的运算方式。当我们学习某个神灯精灵的方言中有哪些型别,我们也会很自然地问说,这个方言中的这些型别又有哪些原生的运算方法。例如,数字的运算方法通常包含加减乘除;文字串的运算方法通常包含字串合并、字串切分、字串搜寻;真假值 / 布林值的运算通常包含而且 (and)非 (not), 以及 或者(or)

在某些神灯精灵语的方言中,型别是很重要的。我们必须告诉神灯精灵,想要它记得的东西是属於哪个型别,它才有办法理解。这其实很好理解,毕竟, 1+"Logos" 会等於什麽!? 根本看不懂啊这句话!因此,在那些方言中,除了要告诉神灯精灵有个变数以外,我们还必须直接告诉神灯精灵,那个变数指到的东西是什麽类型。这种方言,我们会说它们是「强型别」。写起来会像这样:

数字 钱钱 = 1000

但是,在某些很会脑补的神灯精灵文化中,神灯精灵会自己帮我们做判断。例如,它看到 1+"Logos" 的时候,会自动脑补说,阿嬷主人应该是想要把 1 当成文字,然後和後面的文字合并再一起吧!所以,它会把 1+"Logos" 这个指令,当成 "1"+"Logos",结果就会回答 "1Logos"。也因此,我们不需要在宣告变数的时候,指定好这个变数的型别。这种方言,我们就说它们是「弱型别」。

弱型别的方言听起来很美好,但是很多时候,神灯精灵的脑补未必如同我们的想像,也因此会闹出很多错误。因此,在使用弱型别方言的时候,就需要特别注意,在那个文化中,神灯精灵会怎麽理解不同型别的转换,以免神灯精灵做出意料之外的行为喔!

最後,让我们总结以上 4 个神灯精灵语的特徵:

  1. 在我们希望神灯精灵记得我们告诉他的新事物时,必须使用名称,也就是变数,来进行储存。
  2. 这些变数中储存的东西,会分成不同的类型,也就是型别;这是为了要让神灯精灵知道怎麽计算或处理这些东西。
  3. 我们可以让神灯精灵替我们执行不会出错的条件判断
  4. 我们可以让神灯精灵替我们执行重复繁琐的回圈

电脑就像我们的神灯精灵,而程序语言就是我们和电脑沟通的方式。无论我们学习怎麽样的程序语言,我们都可以看看这 4 个特徵,在这个程序语言中会怎麽表达。那麽,接下来,我们就要开始学习 JavaScript 这个程序语言了!


<<:  【ModernWeb'21 VIRTUAL EVENT 议程整理】(非官方)

>>:  Day_29 Docker

Java 语言和你 SAY HELLO!!

第十二天 各位点进来的朋友,你们好阿 小的不才只能做这个系列的文章,但还是希望分享给点进来的朋友,知...

Day23 AWS - EC2

AWS蛮多常用的功能都有提供有限度的免费使用,如EC2、RDS、S3、ElastiCache等,收费...

[Day5] Holt's Model 介绍

第四篇我们介绍了时间序列经典的统计预测方法 ARIMA,包含公式内的两大模型 AR model、MA...

Day 19 Provider小Tips

今天是一个小Tip的日子,当我们在座每项测试案例时,不可能每次都要包Provider吧 太累 imp...

IT管理厂商新电脑入厂的资安第一道防线

设备电脑资安检查承诺书 提供电脑进厂的厂商 , 必需要填写的一份资安切结书. 厂商保证项目: 一.作...