下一章 上一章 目录 设置
28、努力写代码的日常 12.2
...
-
12.2
十月中旬到十一月,我几乎每周都去Ian的office hour。
作业真的太难了。每次 project 截止前的那个周五,BBB 四楼那间教室就成了我的第二个家。我背着电脑走进去,找个角落坐下,打开 VSCode,继续和那些总是跑不通的代码搏斗。Ian 坐在最前面,前面排着队,一个接一个地帮人看代码。有时候人很多,我就先自己改;有时候人少,我刚坐下没多久就轮到我了。
有一次,我卡在一个指针相关的错误上,改了四十分钟都没改对。程序一运行就崩,终端里跳出一行 segmentation fault。我知道多半是内存访问出了问题,可就是找不到到底是哪一处越界了。我只好一行一行往下查,在关键地方加 cout,把变量值、数组下标、循环次数全都打印出来,盯着屏幕看了半天,还是没看出问题。
Ian 那边的人终于走空了。他站起来伸了个懒腰,走过来在我旁边坐下。
“怎么了?”
“指针。”我把电脑转过去给他看,“这个链表插到第三个节点的时候就会崩。”
他低头看了一会儿,没立刻说话,只是一行一行往下读。过了一会儿,他把光标停在某一行,轻轻点了点。
“这里。你这个新节点分配出来以后,next 没有初始化。”
我愣了一下。
“所以它现在指到哪儿都是随机的,”他说,“前面没出事只是运气好。到第三个节点的时候,你再去访问它,就直接崩了。”
他顺手加了一行,把 next 设成了 nullptr。
我重新编译,重新运行。
这一次,程序没有再崩。终端里那几行输出安安稳稳地停在那里,第三个节点顺利插进去了,后面的结果也都是对的。
我盯着屏幕看了几秒,终于长长地出了一口气,整个人往椅背上一靠,像刚从水里浮上来。
“谢谢你,”我说。
“不客气。你其实离答案很近了。”
我点了点头,把代码保存,合上电脑。收拾东西的时候,他还在旁边坐着,没有走。我看了一眼时间,office hour已经超时了快二十分钟。
“你还不走?”我问。
“等你收拾完。”
我笑了一下。他也笑了一下。站起来的时候,椅子腿刮了一下地板,发出一声短促的响。
十一月中的一次 office hour,我终于写完了一个 project。所有测试都通过了。终端里整整齐齐地跳出一排绿色的 PASS,一行一行往下滚。我盯着那些绿色的字看了好几秒,像是有点不敢相信。然后我抬起头,下意识地去找 Ian。
他正坐在最前面,面前没有人。我站起来,拿着电脑走过去,把屏幕转给他看。
“全过了,”我说,声音比我想的要大。
他看了一眼屏幕,然后抬起头来看我。“我说你可以的,”他说。
我站在那里,看着他,突然有一种冲动,想抱他一下。
我的身体往前倾了一点,手臂微微抬起来,然后,停住了。
我的手悬在半空中,像是不知道该往哪里放。Ian看着我的手,又看着我的脸。他的表情没有变,但嘴角的弧度更大了,像是看穿了我脑子里那个没做完的动作。
“恭喜,”他说,声音很轻,像是怕惊动什么。
我把手收回来,垂在身侧。“谢谢,”我说,声音比我预想的要小。我抱着电脑回到座位,假装整理书包,假装刚才什么都没有发生。但我收拾东西的动作比平时快了很多,拉链拉了两遍,水壶塞不进侧袋,我使劲往里塞,指甲卡在拉链上,疼了一下。
我站起来,背上书包,走到门口,说了声“下周见”。Ian抬了一下手,没有站起来。他坐在那里,手里还拿着笔,看着我走出教室。
走廊的灯是热控的,我走一步,亮一盏,走一步,亮一盏。走到楼梯口的时候,我停下来,靠着墙站了一会儿。心跳还是快的。
有一天我去的比较早,office hour还没开始,教室里只有Ian一个人。他坐在最前面,面前摊着笔记本,正在看什么东西。我走过去,把书包放在旁边的椅子上,坐下来,打开电脑。
“你今天来得早。”他说。
“嗯,刚整好在这附近,就直接过来了。”
他没有继续说话,我也没有。我们各自对着各自的电脑,教室里很安静,只有键盘的嗒嗒声。过了大概十分钟,他站起来,走到窗边,把窗户开了一条缝。冷风从缝隙里钻进来,带着深秋的凉意和落叶的味道。他站在那里,背对着我,看着窗外。我不知道他在看什么,也许什么都没看,只是站一会儿。他的背影很高,肩膀很宽,卫衣的帽子垂在身后,像一只趴在他背上的猫。
“林栖。”
“嗯。”
“你进步很快。”
“真的吗?”
“真的。”Ian 说,“你第一次来的时候,一个 for 循环的边界条件能改五六遍。”
“……你还记得?”
“很难不记得。”
我抬头看他。他已经转过去关窗了,像刚才那句话只是随口一说。窗扣有点紧,他用手压了两下才扣上,然后走回来,在我旁边坐下。
“谢谢。”我说。
“谢什么?”
“夸我。”
他低头看自己的电脑,嘴角很轻地动了一下。
“我只是在陈述事实。”
十一月最后一周,作业突然又难了一个台阶。
递归。我完全搞不懂。
函数调用自己,一层套一层,像俄罗斯套娃。拆开一个,里面还有一个,再拆开,还有一个。我知道书上说一定要有 base case,也知道每一次调用都应该离它更近一点,可一到自己写,脑子里还是会乱成一团。
那天我卡在一个斐波那契数列上。答案是对的,就是慢。
我把 n 从 20 改到 30,又从 30 改到 40。屏幕上的光标闪了半天,什么都没有发生。
Ian 那边排了三四个人。我坐在角落里等,一边等一边改,改坏了再撤回,撤回以后又觉得刚才那个版本可能也没那么坏。等轮到我的时候,已经快一个小时了。
我把电脑推过去。
“它不理我了。”
Ian 看了一眼屏幕。
“你对它做了什么?”
“我只是让它算四十。”
“那确实有点残忍。”
我忍不住笑了一下。
他把电脑往自己那边拉了一点,没有碰键盘,只是看代码。
“你觉得它算 fib(40) 的时候,第一步会做什么?”
“算 fib(39) 和 fib(38)。”
“然后 fib(39) 呢?”
“fib(38) 和 fib(37)。”
他说:“所以?”
我盯着屏幕。
过了几秒,我突然看见了。
“……fib(38) 算了两遍。”
“现在是两遍。”他说。
我顺着往下想。
三十七,三十六,三十五。那些数字像树枝一样不断分叉,又绕回来,重复,再重复。
“天啊。”
Ian笑了。
“看见了?”
“它是不是特别蠢?”
“你的程序?”
“嗯。”
“程序是你写的。”
我转头看他。
“你一定要这么说吗?”
“这是事实。”
“你之前还说我进步很快。”
“这两件事不冲突。”
我没理他,重新看屏幕。
“所以我要让它别重复算。”
“怎么让?”
我想了一会儿。
“把已经算过的存起来?”
他没说话。
我抬头。
“对不对?”
“你试试。”
我新建了一个数组。
第一遍写错了。越界。
第二遍还是错,初始值出了问题。
Ian 坐在旁边看着,偶尔伸手指一下屏幕,却一直没碰我的键盘。
第三遍终于跑起来了。
我重新输入 40。
回车。
答案几乎立刻跳了出来。
102334155。
我盯着那个数字看了几秒。
“靠。”
“Language.”
“你又不是老师。”
“我在替 EECS 维护文明。”
我笑了,把电脑往回拉。
可笑完以后,我还是盯着屏幕。
刚才那棵不断分叉的递归树还留在脑子里。一个问题生出两个,两个又生出四个,明明有些东西早就算过了,却还是一次一次绕回去,从头再来。
我忽然觉得,人脑大概也没有聪明多少。
至少我的没有。
有些事情明明已经想过很多遍了,还是会在夜里重新拿出来,从第一步开始,一层一层往下走。每一次都以为这次能得到不一样的答案,最后却只是把自己困在同一个地方。
“懂了。”我说。
Ian正在看自己的电脑。
“真的懂了?”
“真的。”
他转过来看我。
“那下次别再来问同一个问题。”
“那不行。”
“为什么?”
我把电脑合上。
“这样你会失业。”
他看了我两秒,笑了。
那天我走得很晚。
等我终于收拾东西的时候,教室里已经只剩下我和 Ian。走廊偶尔有人经过,脚步声从门外响起来,又很快消失。
我把电脑塞进书包,拉上拉链。
Ian 还坐在前面整理桌上的东西。他把散开的习题纸一张张对齐,在桌面上磕了两下,然后拿起订书机。
咔哒。
我站起来。
不知道为什么,没有立刻走。
“下周是最后一周了,”他说,“期末project deadline之前还有一次office hour。”
“嗯。”
“然后就没有了。”
“没有了,”我说,“学期就结束了。”
他没有接话。他把那沓习题集放进书包,拉上拉链,站起来。我们一前一后走出教室,我走在前面,他跟在后面。走廊很长,灯光是那种柔和的白色,把整条走廊照得很亮,但那种亮是空的,没有温度。我们的脚步声在走廊里回荡,他的步子大,我的步子小,两种节奏交叠在一起,像一首没有旋律的二重奏。
走到楼梯口的时候,他停下来。
“林栖。”
“嗯。”
“期末project好好写。有问题随时来问。”
“好。”
他点了点头,转身往另一个方向走了。我站在楼梯口,看着他走远的背影。走廊很长,灯光很亮,他的影子被拉得很长,拖在地上,越来越淡,越来越远。走到拐角的时候,他回头看了一眼,抬了一下手,然后消失在拐角后面。走廊空了,我站在那盏灯下面,站了很久,直到楼梯间的门自动关上的声音从远处传来。
我转身下楼。天已经黑了,路灯亮着,橘黄色的。
我站在路灯下面,回头看了一眼那栋楼。窗户亮着灯,一间一间的,不知道哪一间是BBB的四楼,不知道他还在不在那间教室里。也许他已经走了,从另一个楼梯下去,从另一个门出去,走另一条路回家。安娜堡的夜晚很安静,没有太多车,没有太多人,只有风,和路灯下自己的影子。
我把围巾往上拉了拉,往公交车站走去。