【BJC】04-3-List Mutation-列表的"变更"

课程链接

  

这节课我们来探讨列表的"变更"(mutation),首先来想一下,如果我们想交换列表中两个值,可以编写一个怎样的模块?我们的输入值需要三项:两项数字来表示我们要交换的值在列表中的位置,还有一项输入值是列表,也就是我们的目的列表。

 

 注意这里的data值在设定时应选择类型为list,并且输入值为Single input。整个模块应设置为list模块。

 当你完成后,应该就是这个样子:

 

 

 当你设置一个叫做game board的列表变量,试试用它来交换:

 

 交换前:

 

 交换后:

 

 我们做出的这个交换数值的模块就是列表变更(list mutation)的一个例子,它可以改变现有列表中的项(item),而不需像那样新建一个列表来完成,这样就比拷贝一个列表再剔除要交换的项要省事儿多了。然而,变更也可能产生一些结构化编程中不会出现的bug,比如当一个主程序中有两个子程序都用到同一个list,当一个子程序改变了list时,另一个子程序可能就会出错。这跟我们在02-4-函数一课中学到的函数式编程(functional programming)有所不同,对于函数式编程来说,输入值一旦确定,就没有任何东西可以影响它的输出了,而这里一个部分的变更(mutation)却影响了另一个部分的计算,因此并不是严格意义上的函数式编程。你可以回过头看一下这篇知乎讨论,里面关于函数式编程immutable的优劣有比较深入的观点。

 

其实我们并不是第一次接触到变更(mutation),比如说"for"模块

 

 里面的变量"i"的值就会随着循环的进行而改变,但由于这里的"i"是一个局部变量,只在for循环中存在,所以并不会影响到其它程序的运行。但当一个变量是全局变量(global variable)时——比如上文例子中的game board变量,改变(mutate)它就会有些风险了,因此一般情况下我们推荐用脚本变量(script variable)。

 

接下来我们看看一些非常tricky的例子。

 例1:假定我有一个全局变量"foo",并且定义如下两个模块:

    

 然后我执行下面这个脚本:

 

 你觉得变量"foo"的值现在是多少呢?100?105?120?还是125?

 例2:我们把"foo"换成一个列表变量再做一个类似的实验:

     

 

 那么现在列表"foo"中会包含什么呢?

 以上模块建议你自己动手操作一遍,如果实在不方便呢也可以点这里运行我设置好的~运行后在舞台(stage)上就可以看到相应变量的值了。

 

为什么会有这样的区别呢?给"foo"加5的那个模块是直接作用于"foo"的,所以能改变它的值,但为什么你能把20作为一个新的项加到列表里,却不能让"foo"的值增加20呢?难道是Snap!本身有问题么?

 其实Snap!在这两个例子中执行的是同样的原则。要想明白这个原则,你首先必须分清楚什么是值(value),而什么是变量(variable)。值(value)可以是一个数字、一串字符、布尔值(真/假)或是一个列表;变量(variable)本质上则是变量名和一个值之间的联系。(这里对于变量的定义与其它编程语言稍有不同,不过在你学习其它语言前它已经够用了)。

 像大多数编程语言一样,你给模块(block)提供的输入值是值(value),不管这个值是直接输入的,还是计算出的,还是从另一个变量那里获得的。直观点来说就像下面这样:

 

 看到这个你还会觉得"foo"的值变了么?变到123还是117?稍微想想就会明白,"add 20 to"模块的输入值是103,即的结果,而不是变量"foo"本身,所以"foo"的值并不会变。同样在之前的例1里,"add 20 to"的输入值是105(因为"add 5 to foo"模块确实让"foo"的值加了5,变成了105),而不是"foo"。

 "add 20 to"定义中的"change"模块确实改变了var的值,但var是局部变量,只存在"add 20 to"模块中,当这个模块结束,var也就不存在了,并不会影响到其它程序。

 但是当"foo"的值是一个列表(list),事情就会有些不同了。与数字不同,列表本身就是可变的(mutable),当然你说值为数字的变量也是可变的,那仅限于我们把它放到change或者set模块中时。当我们在例2中运行append模块时,列表变量"foo"还是那个列表,但列表中的元素增加了。也就是说,它的身份(identity)没变,只是内容改变了。这就好比说某同学张三,他学了我们这门BJC课,虽然他的知识储备增加了,但你不能说他就不是张三了吧?

  

今天的课程比较烧脑,你可以在Snap!中多试试多琢磨一下,我们下节课见啦~

  

**************************

 如果愿意和我一起学习,或有什么翻译方面的意见和建议,欢迎联系我~花名咖啡酱^_^

 每集课程都要自己看过后翻译总结,制作不易,转载请注明出处哟~

LOFTER: https://amandadsun.lofter.com/

Gmail: amandadsun@gmail.com

 微信: Amanda_D_Sun

 

评论
热度(2)
© 咖啡磨成酱 | Powered by LOFTER