我曾经带过一个女生。很伶俐大方的一个小姑娘,211院校毕业生,怎么都傻不了。 当时分配给她的是类似这样的一个任务。首先上游函数会传来这么一个文本表格: 1 2 3 4 T 这个表格存于变量textTable中,需要调用lines = split(textTable, '\n')按行拆分,执行后print lines[0]结果为: 1 2 3 4 T 其它依此类推。 然后,对每一行,继续line = split(lines[0], '\t'),按空格把这一行内容分开。 这时候print line[4],输出为 T 如上检查每一行,如果其中至少有一行的第五列是F,那么返回false;否则返回true。 当然了,正常程序员接到的任务应该只有一句话:分析这个表格,第五列出现F就返回false,否则返回true。具体解决方案的设计是接任务者的工作。 她是初学者,所以我先问:“你对编程语言有了解吗?” 答曰:“计算机二级考过。” “既然过了计算机二级,看来我不用从头给你讲什么常量变量分支循环了?” “不用,不用!” “这个命令”,我在TCL交互环境敲了个split,“知道敲哪里吗?知道怎样存成程序文件吧?” “知道,知道!” 于是便直接开始分析任务。先介绍split函数的功能,然后在命令行直接敲出来给她看效果;如此两步split分解,任务轻松完成。 讲完,我就问:“能看懂吗?把这些步骤写进一个循环,问题就解决了……” “懂了!懂了!” 评论区很多人对“通过二级不用讲基础知识”有疑问,我把那段对话修改了一下,避免了其中的歧义(时间太长,具体措辞肯定有出入;但按我的习惯,和一个陌生人对话,开场白应该是这样:先确认前置条件是否满足,然后在可以达成共识的最高断面的基础上开始讲解)。 第二天,她来找我了:“怎么不行啊……” 一看,她是这么写的: split(textTable, '\n') 这是对变量完全没概念啊。 我就给她解释,split的结果你得先存到lines变量里,lines变量就好像一个盒子,textTable是一大盒粉笔,你用split之后就把它变成一打一打小包装的若干小盒粉笔,这些粉笔先放在lines这个盒子里;然后,你要用一个循环,把lines这个盒子里的每一小盒粉笔取出来,找其中的第五支…… 仍然是一边说,一边把每条语句都敲出来给她看效果。当然,仍然没直接演示循环该怎么写——她能自己摸索出来才说明是真懂了。 讲完,再问:“能听懂吗?” “好像没问题……” “那你回去试试,有不明白的问我。” 第三天,她又来了:“还是不行啊……” 这次她是这么写的: lines=split(textTable, '\n') 这是对数组完全没概念啊。 我继续给她演示:“lines是一个数组,你看,它里面的内容打印出来是这个样子……” 一边说,一边敲了个print lines,屏幕显示: ["1 2 3 4 T", 然后敲print textTable,屏幕显示: "1 2 3 4 T 提示她:“看出不同来了吗?textTable是一个字符串,lines是一个字符串数组。所以当我们敲print lines[0]时,就把lines里面的第一个字符串提取出来,传给了print……” 如此这般,把每一个细节都敲出来给她展示清楚。末了,问她:“能听懂吗?” “能听懂,讲很清楚……” “那能不能自己写出来呢?” 面露难色:“我试试吧……” 如此这般,第四天,第五天,第六天,第七天…… 两个星期过去了,她终于……彻底把我敲出来的示例背下来了。 现在她的程序长这样: lines=split(textTable, '\n') 当时那个用作示例的表格有十几行,她一行一行都写了出来。 嗯,期间还发生了别的很多事情。比如刚开始我只要求她把每一行都分解成列表显示出来,她搞不定,私下找了其他同事帮忙——那个return false什么的都是别人教的。 总之吧,她总算是把虽然僵硬但毕竟还能通过示例数据的东西弄出来了。 “你这样可不行啊。将来表格内容是会变的。有的只有两行,你这个到后面就得出现非法访问;有的又可能有几千行……所以这里必须改写成循环。喏,你看……” 我敲了个: foreach line in lines { “明白了吗?你看,循环可以把lines里面的每个元素依次提取出来,然后你把print那里替换成分析line的代码,问题就解决了……” “好难……” 教你更难——这句话我没敢说出口。 没办法,照旧在命令行敲出来演示(脚本语言就这点好);为了方便她理解,从二级考试的C风格for循环、while循环开始演示,一路演示到foreach。 “懂了吗?” “好像……还是有点不太明白……” “那我再给你演示下……” “不用不用,我都记住了……就是……嗯,我回去试试。” 之后又是好些天。我教的foreach语法在当时还是个新鲜玩意儿,学校不教;学院派当时习惯用for——她显然找人问了,我教她的简易又安全的foreach她不用,拿来个for版本的: for(,,) 还是一行行手工处理,就是额外加了个死循环;末尾的return true仍然不知道加上。 而且,这种语言,for后面不加括号直接换行就是个空白循环;还有,for里面是分号,用逗号是语法错误…… “编程语言语法很重要,格式一点都不能错。这是语言官方手册,看过吗?” “看过……” “喏,你看,这是for循环的语法……” 过了一天,她拿来这个: for(,,); for里面两个逗号打死不改,死循环打死不改;for语句后面可省略的分号加上了——昨天发现的一切问题照旧。 没办法,从头给她讲格式,讲循环变量,讲循环体。末了,照例问“懂了吗?” “不懂……” “嗯……觉得哪里不明白?” 她眼圈直接红了,眼泪差点流下来:“都不懂……” 都不懂……这下麻烦大了。我从语句讲起,讲什么是一条完整的语句,讲语句中哪些地方可替换,讲编程手册那些符号的意思(人家明明一开始就讲了的)。很显然,这对她是天书…… 没办法:“要不我给你写个正确的,你回去看看书,把它改成while版本的?” “好” 于是我给她写了个for版的: lines=split(textTable, '\n') 照例把每个元素敲命令行让她看了一遍,确保没有不理解的地方。 其实这里用foreach更好: foreach line in split(textTable, '\n') { 四行代码解决问题。 不过我们的目标又不是教她写这个函数。真给我们干就几分钟的事,耗这么久就是要她真正掌握编程。所以我教她用for,还要她自己想办法改成while循环。 一天后,她还回来这样一个while版的: lines=split(textTable, '\n') 时间久,我记不清了。她写的错漏之处更多。 这简直要把人逼疯了。 没办法,一点点讲解,for是什么原理,while是什么原理,为什么她那个while不合语法…… 同期的其他学员大多通过了考核,就剩她了。现在成了好多人教她一个的局面。当然,主要负责人还是我。 总之,我教她思路,然后她私下找人问;别人不愿直接给她代码,怕耽误她的学习,就故意给思路不同甚至绕个大弯的其他方案。于是每天她拿来的代码总带着别人帮忙的痕迹,然后又被她乱七八糟的糅合进去…… 我就给她讲这些代码都是什么思路,为什么不能胡乱拼凑过来,告诉她必须自己理解了才能做对。但她就是不能理解。 我很快发现她只是在死记硬背,其实压根不知道每行代码的含义。只要顺序稍微一打乱、或者书写格式稍有变化、或者把split之类语句稍微绕个弯写(比如写成delimiter='\t',split(line, delimiter)),她就答的差三落四。 我就告诉她,一定把split、for等等东西都拆分出来,一个个敲命令行看看效果;变量和数据类型之类基本概念必须搞懂。我还一遍遍给她讲程序控制流的概念,给她描述CPU怎么执行这些语句,演示每一行执行前后的变化…… 但是连一点用都没有。她完全理解不了这些字母的意义。大概在她看来,程序代码就是些神秘的咒语。你讲再仔细,咒语也只是不可理解的咒语…… 如此熬了一个多月,任务时限到了。 她拿着我给她写的那个for版程序试图蒙混过关,然而验收者明察秋毫:“去把for改写成for(index=lines.length-1; ...)” 就这样,她又原形毕露了。 眼圈红红的找过来:“不会写……他还让我解释每一句都是干什么的……” “……哪句不明白?我给你解释……” “哪句都不明白……”,她突然崩溃,带着哭腔。整个实验室的人都转过头来看我们。 没办法,我只好再次一行行敲进去给她演示,解释那是干什么用的。但她心不在焉,一点都没听进去。 看她可怜兮兮的,我只好给她找个台阶下:“回去把那份初学者指引多看看,把里面的例程都敲出来试试。这个有点难,一上来就做这个门槛有点高。” “好”,仍然带着哭腔。 之后,我再也没见到过她。 |
|