跳到主要内容

迁移与迷思概念 — 旧知识是助手还是内鬼

这一章讲三件事: 旧知识什么时候帮倒忙;一种特殊的思维错误——迷思概念——为什么特别顽固; 以及「学会忘掉」为什么是一种正经的学习能力。 它是第 07 章的续集:那章说旧模型会乱入,这章说乱入的模型怎么固化、怎么拆。

1. 全景:迁移的两副面孔

已有知识 ──→ 学新语言/新框架
├─ 帮忙:变量、循环、类这些概念不用重学 → 正迁移
└─ 捣乱:拿旧语言的规矩套新语言 → 负迁移
↓ 固化
迷思概念(坚信不疑的思维错误)
↓ 很难洗掉
概念转变 + 忘却学习 + 长期抑制

图说:迁移本身没有好坏,好坏取决于「旧知识在新领域还成不成立」。

迁移就是已有知识在新场合派上用场——会下国际跳棋的人学国际象棋更快,会 Java 的人学 Python 不用重学「什么是循环」1。它分两个方向:学习过程中的促进(拿 Java 的方法概念去类比 Python 的方法)是一路;把技能整体搬进陌生场合(买新裤子不用学扣扣子)是另一路2

2. 迁移是吝啬的:六个影响因素

先泼冷水:迁移不会自动发生。它受六个因素控制3:

因素内容一句话版
掌握原领域学得多深半吊子的 Java 迁不出多少东西
相似性两个领域共同点多不多熟悉的算法+陌生的语言,比双陌生好迁
情境环境像不像换语言别顺手换 IDE——情境断了,迁移也断
关键属性知不知道该迁什么明说「JavaScript 经验对学 Python 有用」,人会主动找共同点
联想名字、记忆上的勾连Java 和 JavaScript 名字像,联想就强——虽然它俩几乎没关系
情绪你对旧知识的感受和二叉树打交道一直愉快的人,新任务里更愿意用它

迁移还分主动和被动:低阶迁移是无意识的(Ctrl+C、Ctrl+V 换个编辑器照按不误),高阶迁移是有意识的(「Python 靠缩进分层,JavaScript 有类似规矩吗?」)4。按距离还有近迁移(C# 迁 Java)和远迁移(Java 迁 Prolog)——远迁移发生的可能性小得多5

迁移有多吝啬,两项研究给出了底:国际象棋大师的记忆优势只在真实棋局上成立(第 02 章的乱摆棋局),换记数字、记图形就和平人一样,棋艺也不会外溢到别的逻辑游戏6;编程教育研究了多少年呢——1987 年萨洛蒙(Salomon)汇总已有研究,结论是编程对一般认知能力的影响几乎可以忽略7。所以「学编程练脑子」「学棋益智」这类话,证据都不站在它们那边。作者的实用推论:想靠学新语言拓展思维方式,就选一门和你会的完全不同的语言——只在「乡村音乐」内部扩展到「西部音乐」,听一百张专辑也是原地踏步8

3. 负迁移:旧知识埋的雷

旧知识帮倒忙时,就叫负迁移。它不可怕 if 你知道它在;可怕的是负迁移造出的错误假设你不知道。书里给了三颗不同深度排的雷9:

  • 浅雷:Java 变量必须先初始化再用,老 Java 程序员默认 Python 也这样——一查便知;
  • 中雷:Java 的受检异常(编译器强制你处理的异常类型)是 Java 特有的,C# 程序员转 Java 时意识不到「自己熟悉的异常概念」和眼前这个东西不一样——模型错了却全然不知;
  • 深雷:面向对象的老手学函数式语言(函数是一等公民、没有副作用的那类语言,如 F#),发现「函数」这个词自己认识、用法却完全两样——旧概念的根扎得太深,新范式整个学不动。

4. 主走查:「变量只能存一个值」是怎么长成的

迷思概念的正式定义有三条:不正确;在不同场合反复出现;当事人坚信不疑10。「辣椒籽最辣」是教科书案例——不正确(辣味在果肉里)、以讹传讹人人复述、信的人做菜前认真去籽11。编程圈的版本,拿书里点名的那条走一遍:新手认为变量(比如 temperature)只能存一个值,不能再赋新值12

这条迷思的长成过程,每一步都有出处:

第 1 步(数学课):x 存进方程后就是个固定记号
→ 数学里的变量「确实」不变 —— 这不是错,是旧领域的正确
第 2 步(负迁移):把这个正确搬进编程
→ 「temperature 被赋过值了,所以不能再赋」
第 3 步(日常经验加固):文件系统的类比来帮忙
→ 同一个文件夹不能建两个同名文件;
「temperature 已经被占用了」——第二个日常模型确认了第一印象
第 4 步(固化):三条迷思标准集齐
→ 不正确(变量随时可重赋)+ 反复出现(每次写赋值都犯)
+ 坚信不疑(错误消息都读不懂,因为「不可能报错」)
第 5 步(难洗):告诉他「变量可以重新赋值」?
→ 没用。见下一节。

注意第 3 步:迷思很少只有一个来源——负迁移负责点火,另一个似是而非的日常模型负责浇油。烤肉「封住肉汁」的迷思同构:从煎蛋「外层受热会凝固」迁移来,其实烤肉让水分跑得更快13

5. 为什么「告诉他错了」没用

迷思概念的顽固有硬机制。第一条:记忆不删除。第 07 章说过旧模型会乱入,这里说的是同一件事的另一半——科学界目前认为,错误概念不会从记忆里消失,哪怕你已经用正确概念解过题,旧概念还在,还在等机会14

第二条:正确要靠「抑制」旧概念,而不是覆盖它。加加利与巴尔(Galili & Bar)发现:学生明明会熟练地用力学知识解题,遇到更复杂的新题时却退回更原始的错误推理15。大脑要得出「雪人穿毛衣化得慢」,得主动压住「毛衣=保暖」的第一反应——如果换个思路时你有过那种「等等,不对,再想想」的迟疑感,那就是抑制机制在干活16。作者自己也交了一个:她曾长年坚信「函数式语言都支持惰性求值」(先不着急算、用到再算),因为她只见过 Haskell——第一个样本冒充了整类17

所以纠错的正式名字不叫「学会」,叫概念转变:新模型不是加进旧图式,而是取代旧模型的位置——这是记忆结构层面的动工,比常规学习费劲得多18。配套动作叫忘却学习(unlearning):Java 转 Python,难的不是记住「Python 不用声明类型」,而是戒掉「写每一行都想类型」的肌肉习惯19

6. 迷思图鉴:四条最值得背在身上的

赫尔辛基阿尔托大学的索尔瓦(Sorva)在 2012 年的博士论文里汇总了162 种编程迷思概念。书里挑了四条最有启发性的20:

编号迷思它为什么「说得通」
15 号total = maximum + 12 存下了一个关系,改 maximum 后 total 跟着变」数学里的等式确实是关系;有些语言(Prolog)真的这么干
33 号「while 循环每执行一行都检查条件,条件一假立刻退出」英语的 while 就是这个意思——「下雨时我就在这儿看书」,雨一停就走
17 号「叫 minimum 的变量只能存最小值」名字即命运的直觉
46 号「函数定义和调用处必须用不同的变量名」「名字只能用一次」的规矩在函数边界上悄悄失效了

这四条的共性值得看穿:每一条都是从另一个正确情境迁移来的「合理错误」——数学、英语、变量命名的单一职责。它们不是蠢,是迁移太勤奋。46 号还有个附加教训:同一门语言内部也会负迁移(函数外的规矩想当然带进函数内),不止跨语言才出事21

7. 对策:防、查、压

迷思没法根除,只能管理。书里的建议分三层22:

  • :学新语言前,主动问「这门语言和我已会的哪里不一样」——把「关键属性」因素喂饱,迁移才走对方向;对照迷思清单(比如 Sorva 那份)逐条自查;
  • :结对与评审时把各自的假设说出来——两个人的假设一对撞,迷思立刻现形;对资深人士尤其要紧,权威身份会让人放弃怀疑自己;
  • :给「坚信不疑」的假设写测试——「这个值不可能小于零」就写一个断言(程序里的一句自动检查,不满足就报错);再在代码旁边留文档,提醒下一个人(以及未来的你):这里曾经有个想当然23测试和文档是外挂的抑制机制——你脑内的抑制会累,机器的不会。

8. 作者的判断与证据

**有实验或文献撑着的:**迁移吝啬(棋艺不外溢的系列研究;萨洛蒙 1987 年的汇总);概念转变与抑制(加加利与巴尔;认知科学关于记忆不删除的主流看法);迷思清单(索尔瓦 162 条,均为二手汇总——即每条迷思背后另有原始研究)。

作者的发挥,要分开看:「负迁移催化的迷思」这个因果框架(如烤肉例子)是作者的整合叙述;她对自己 Haskell 迷思的交代是自我报告;「乡村音乐/西部音乐」的选语言建议是个人判断。

书的坦白:「科学家虽然不清楚大脑究竟如何决定使用哪种已有的概念」——抑制机制怎么被调度,书里承认还没有定论。

9. 边界与局限

  • 索尔瓦清单收的是初学者迷思;资深工程师的迷思(往往藏在架构假设里)研究少得多——本章机制适用,清单帮不上忙;
  • 萨洛蒙的结论(编程教育对认知影响可忽略)针对的是「学编程能否提升一般智力」,不否定「编程教人编程」——别读成「学编程没用」;
  • 「迷思永远压不干净」意味着测试要长期留在原地:写成一次的断言,防的是下一个人和十年后的你,不只是这一次;
  • 本章与第 03 章的精细加工是同一枚硬币:主动连旧知识加速学习(正迁移),也顺手把旧概念的错误直觉带了过去(负迁移)——没有只有一半的操作。

10. 可带走的

  1. 学新语言前先列「我预期哪些一样、哪些不一样」——把迁移从碰运气变成有意识动作;
  2. 换语言时别顺手换 IDE 和干活套路,情境是迁移的桥;
  3. 「我觉得这不可能出错」的地方,就是写断言的地方;
  4. 迷思的三条标准(不正确、反复出现、坚信不疑)可以拿来给人做诊断——反复犯同一类错=有迷思,不是态度问题;
  5. 纠正别人时别指望「告诉一遍」生效——概念转变是动工,不是知会一声;给对方留重建模型的时间和抽认卡;
  6. 那种「等等,不对」的迟疑感值得尊重——那是抑制机制在帮你压旧模型;
  7. 团队评审时请资深的人也说出自己的假设——权威是迷思最好的保护伞。

11. 原文地图

主题原书章原文位置
迁移定义与两种7.1 为什么学习第二门编程语言比学习第一门编程语言更容易text/44-ch07-01-7-1.txt:5(搜「称为迁移」) · text/44-ch07-01-7-1.txt:7(搜「学习中迁移」) · text/44-ch07-01-7-1.txt:23(搜「学习迁移(transfer of learning)」)
六因素7.1 为什么学习第二门编程语言比学习第一门编程语言更容易text/44-ch07-01-7-1.txt:35(搜「掌握」) · text/44-ch07-01-7-1.txt:43(搜「联想」) · text/44-ch07-01-7-1.txt:45(搜「情绪」)
低阶/高阶、近/远7.1 为什么学习第二门编程语言比学习第一门编程语言更容易text/44-ch07-01-7-1.txt:53(搜「低阶迁移」) · text/44-ch07-01-7-1.txt:57(搜「远迁移」)
负迁移三颗雷7.1 为什么学习第二门编程语言比学习第一门编程语言更容易text/44-ch07-01-7-1.txt:69(搜「摧毁大脑」) · text/44-ch07-01-7-1.txt:71(搜「先赋值,后使用」) · text/44-ch07-01-7-1.txt:73(搜「受检异常」) · text/44-ch07-01-7-1.txt:75(搜「函数式语言」)
迁移难与萨洛蒙7.1 为什么学习第二门编程语言比学习第一门编程语言更容易text/44-ch07-01-7-1.txt:85(搜「泼了一盆冷水」) · text/44-ch07-01-7-1.txt:87(搜「忽略不计」) · text/44-ch07-01-7-1.txt:89(搜「乡村音乐」)
迷思三条件7.2 迷思概念:思维中存在的错误text/45-ch07-02-7-2.txt:11(搜「才属于迷思概念」) · text/45-ch07-02-7-2.txt:19(搜「辣椒籽」)
烤肉封肉汁7.2 迷思概念:思维中存在的错误text/45-ch07-02-7-2.txt:27(搜「封住肉汁」)
变量单一值迷思7.2 迷思概念:思维中存在的错误text/45-ch07-02-7-2.txt:29(搜「只能存储一个值」) · text/45-ch07-02-7-2.txt:31(搜「temperature已经被占用」)
概念转变与忘却学习7.2 迷思概念:思维中存在的错误text/45-ch07-02-7-2.txt:37(搜「概念转变(conceptual change)」) · text/45-ch07-02-7-2.txt:41(搜「忘却学习」)
记忆不消失与抑制7.2 迷思概念:思维中存在的错误text/45-ch07-02-7-2.txt:49(搜「不会消失」) · text/45-ch07-02-7-2.txt:51(搜「抑制」) · text/45-ch07-02-7-2.txt:53(搜「抑制性控制机制」)
作者的 Haskell 迷思7.2 迷思概念:思维中存在的错误text/45-ch07-02-7-2.txt:57(搜「惰性求值」)
Sorva 清单与四条7.2 迷思概念:思维中存在的错误text/45-ch07-02-7-2.txt:61(搜「162种」) · text/45-ch07-02-7-2.txt:63(搜「15号迷思概念」) · text/45-ch07-02-7-2.txt:69(搜「33号迷思概念」) · text/45-ch07-02-7-2.txt:75(搜「46号迷思概念」)
对策与测试文档7.2 迷思概念:思维中存在的错误text/45-ch07-02-7-2.txt:90(搜「对照这份列表」) · text/45-ch07-02-7-2.txt:104(搜「编写测试」)

Footnotes

  1. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 5 段(text/44-ch07-01-7-1.txt:5,搜「称为迁移」)。

  2. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 7 段(text/44-ch07-01-7-1.txt:7,搜「学习中迁移」)与第 23 段(text/44-ch07-01-7-1.txt:23,搜「学习迁移(transfer of learning)」)。

  3. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 35–45 段(text/44-ch07-01-7-1.txt:35,搜「掌握」)。六因素依次见第 35、37、39、41、43、45 段。

  4. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 53 段(text/44-ch07-01-7-1.txt:53,搜「低阶迁移」)。

  5. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 57 段(text/44-ch07-01-7-1.txt:57,搜「远迁移」)。

  6. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 85 段(text/44-ch07-01-7-1.txt:85,搜「泼了一盆冷水」)。

  7. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 87 段(text/44-ch07-01-7-1.txt:87,搜「忽略不计」)。萨洛蒙的研究完成于 1987 年,特拉维夫大学。

  8. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 89 段(text/44-ch07-01-7-1.txt:89,搜「乡村音乐」)。

  9. 出处:「7.1 为什么学习第二门编程语言比学习第一门编程语言更容易」第 69–75 段(text/44-ch07-01-7-1.txt:71,搜「先赋值,后使用」)。迪杰斯特拉的反 BASIC 立场见第 69 段,受检异常见第 73 段,函数式困境见第 75 段。

  10. 出处:「7.2 迷思概念:思维中存在的错误」第 11–17 段(text/45-ch07-02-7-2.txt:11,搜「才属于迷思概念」)。

  11. 出处:「7.2 迷思概念:思维中存在的错误」第 19–25 段(text/45-ch07-02-7-2.txt:19,搜「辣椒籽」)。

  12. 出处:「7.2 迷思概念:思维中存在的错误」第 29 段(text/45-ch07-02-7-2.txt:29,搜「只能存储一个值」)。

  13. 出处:「7.2 迷思概念:思维中存在的错误」第 27 段(text/45-ch07-02-7-2.txt:27,搜「封住肉汁」)。

  14. 出处:「7.2 迷思概念:思维中存在的错误」第 49 段(text/45-ch07-02-7-2.txt:49,搜「不会消失」)。

  15. 出处:「7.2 迷思概念:思维中存在的错误」第 51 段(text/45-ch07-02-7-2.txt:51,搜「抑制」)。研究者为耶路撒冷希伯来大学的 Igal Galili 与 Varda Bar。

  16. 出处:「7.2 迷思概念:思维中存在的错误」第 51 段(text/45-ch07-02-7-2.txt:51,搜「稍等片刻」)。原文:出现「稍等片刻」的感觉,表明大脑可能在努力抑制不正确的想法。

  17. 出处:「7.2 迷思概念:思维中存在的错误」第 57 段(text/45-ch07-02-7-2.txt:57,搜「惰性求值」)。作者自述曾认为所有函数式语言都支持惰性求值。

  18. 出处:「7.2 迷思概念:思维中存在的错误」第 37、39 段(text/45-ch07-02-7-2.txt:37,搜「概念转变(conceptual change)」)。

  19. 出处:「7.2 迷思概念:思维中存在的错误」第 41 段(text/45-ch07-02-7-2.txt:41,搜「忘却学习」)。

  20. 出处:「7.2 迷思概念:思维中存在的错误」第 61 段(text/45-ch07-02-7-2.txt:61,搜「162种」)。15 号见第 63 段,33 号见第 69 段,17 号见第 73 段,46 号见第 75 段。

  21. 出处:「7.2 迷思概念:思维中存在的错误」第 82 段(text/45-ch07-02-7-2.txt:82,搜「同一门语言」)。原文指出 46 号迷思概念揭示了编程语言内部的迁移问题。

  22. 出处:「7.2 迷思概念:思维中存在的错误」第 88–100 段(text/45-ch07-02-7-2.txt:88,搜「心态开放」)。

  23. 出处:「7.2 迷思概念:思维中存在的错误」第 104 段(text/45-ch07-02-7-2.txt:104,搜「编写测试」)。「外挂的抑制机制」为本拆解的概括,原文的说法是测试「既能帮助程序员判断自己的假设正确与否」,也是文档。