通过控制过程来缩小差距

目前,我们已经了解到认知和行动间存在着实质性的差距。仅仅知道某事并不足以将其付诸行动,这一事实既无显著性也不便上升为理论;事实上,多年以来心理学家也对这一点感到困惑。早在威廉·詹姆斯的时代,反向的假设——一条直线将人类大脑认知输入和恰当行为输出连接在一起——已成为许多心理学家的基础思想。这种思维方式作为心理学的主导流派,一直延续到了20世纪的早期。

直至我们开始自己制造能运算的机器,即现代计算机时,认知心理学家才认识到要驱动机器做事,必须要有控制结构。计算机给心理学家示范了一个可以自我控制的执行主体(executive agent),并展示了第一例控制过程,即计算机程序的控制流程。

现如今,大多数电子产品,如台式电脑、平板电脑、智能手机、汽车、咖啡机、洗衣机等,都内置电脑芯片,基于程序运行。程序本质上是告诉计算机应该做什么的指令列表,这些列表可能相当庞大。例如,一个简单的iPhone应用程序可能有约1万行代码,Mac OSX Tiger操作系统有超过8000万行代码,谷歌的所有互联网服务估计有近20亿行代码。这些程序之所以这么长,是因为计算机非常依赖于逐字识别,无法领会指令的要领。想让计算机做任何事情,命令必须准确明了。因此,计算机编程让心理学家清楚地认识到认知与行动之间有着巨大的鸿沟。

为了说明这一点,假设想让计算机根据我给出的任意两个数字做求和运算。我可能会给出如下指令:

输入第一个数字

将第一个数字设为X

输入第二个数字

将第二个数字设为Y

在存储的加法表中查找“X+Y”

结果设为变量ANSWER

输出ANSWER值结束程序

上面,我用的是程序员口中的“伪代码”来阐释,伪代码是指一连串类似程序的命令,这些命令并不符合真实的计算机语言(如C++或Python),真正的编码会更加明确。尽管如此,伪代码足以说明控制流程是如何使计算机完成任务的。这个小程序可以用于将任意两个设为X和Y的数字相加,为此我在计算机的查询表中存储了一个求和运算条目。

每当我想把两个数字相加时,都要重写这些指令,令人烦不胜烦。对于这样一个常见的任务,一个实用技巧是把它存储为一个单独的子程序,以便在需要时调用出来。现在有了这个求和小程序,我会把它存储为一个名为“add_2”的子程序,并在我想将两个数字相加时随时调用。

然而,重要的是,完成大多数任务时,我不能任意调用子程序。相反,这些子程序必须在特定的时间,通常在特定的条件下被调用。例如,如果我想让程序只在执行名为“收银机”的任务时将指定两个数字相加,该怎么办?我可以使用一个控制程序,即一个“条件”语句。例如,我可以编写以下代码:

用户输入任务

将任务设为变量TASK

如果TASK的值为“收银机”

然后运行add_2(两个数字相加的指令)否则

输出“我无法完成任务”结束程序

如果用户告诉计算机,它要执行收银机的任务,那么编写的小程序将执行add_2子程序。对于任何其他任务,程序将只会输出“我无法完成任务”。这是分支控制结构(branching control structure)的示例,与遇上岔道口类似,在满足一个分支条件的前提下,程序将沿着该分支运行下去,反之则沿着另一分支运行。

控制流程定向(Directing control flow)实质上可允许计算机执行更复杂的任务。例如,我们的收银机程序迄今为止都不尽如人意,因为它在结账时最多只能合计两项。如果你还需要添加其他物品,则需要重新排队。因此,我们应该希望收银机能够接受任意长度、任意顺序给出的一系列物品的价格,并将它们相加在一起。为此,我可以添加另一个分支控制结构,即“循环”语句,使我可以重复地调用编写的add_2子程序,即将每个新物品的价格添加到不断增加的总价中,直到没有物品需要被添加为止。

计算机具有存储数据的内存,在本例中它类似于加法表。计算机有各种设备,例如输入设备:键盘和触摸板,输出设备:屏幕和扬声器。它还内置了许多操作和子程序,例如add_2,这可能类似于我们的自动操作程序。但是,要使计算机执行某些操作,例如执行名为收银机的任务,必须在正确的时间和正确的条件下将控制流程从一个子程序传递到另一个子程序。控制流程确定计算机执行的操作是否相关、程序需要执行多长时间、程序执行是否要停止。严格来说,这些控制指令本身并不执行任务,分支结构和循环控制结构不添加数字或不输出结果。相反,这些控制指令指挥为整体计算目标服务的处理流程。这种流程的控制是必要的,以使较小的部分以正确的方式协同工作,以完成一个更大的任务。

认知心理学家将计算机程序及其控制结构类比为人类认知控制,对理解人类认知控制有指引作用。在这些早期的想法中,最闻名的是由乔治·米勒(George Miller)、尤金·加兰特(Eugene Galanter)、卡尔·普里布拉姆(Karl Pribram)提出的测试—操作—测试—退出(Test—Operate—Test—Exit)结构,或称为TOTE。TOTE试图描述人类行为的控制结构,并对任意认知控制系统的几个特征提供了有益的说明。基本的TOTE结构如图1.2A所示。

TOTE本质上是用来描述人类行为的环形图。在初始的“测试”阶段,输入系统的信息将与特定条件进行比对。如果不满足该条件,则所需条件与输入信息之间的不匹配会驱动一个操作的“执行”。执行此操作后,再进行“测试”。如果仍然不匹配,则再次执行此操作,依此类推,直到满足测试条件时,循环“退出”,将控制传到下一个TOTE。

想弄明白控制系统是如何运行的,考虑一下吃香蕉时可能用到的TOTE结构(如图1.2B所示)。首先,需要做一项测试,我们将其称为“饱腹感测试”。如果测试显示我们处于饥饿状态,那么这种饥饿状态与饱腹测试条件之间的不匹配会驱动“吃香蕉”这一操作的进行。在循环图中,我们将不断地吃香蕉直到饱为止。这时,当再次测试饱腹感时,我们将退出TOTE。我们有一个简单的控制结构,决定我们何时吃香蕉以及吃多久香蕉。

当然,以上TOTE结构过于简单,这很可能不是我们大脑中执行吃香蕉计划的真实写照。目前没有任何心理学理论信赖米勒、加兰特和普里布拉姆所描述的TOTE。但是,即便TOTE框架过于简单,却言简意赅地说明了有关控制系统基本结构的一些关键要点。

第一,TOTE结构清楚地说明了仅仅知道自己想要做某件事是不够的。想做一件事,就需要用心制订一项行动计划。例如,组织和更新测试条件、适时引导控制流程去执行正确的操作,如“吃香蕉”。这些测试条件不一定出现在初始目标中,它们可能因为情况不同而发生变化。因此,必须有某种控制流程来组织我们的行为。

第二,TOTE结合了条件测试和反馈的概念(反馈是动态管理控制流程的一种方式)。换句话说,根据客观世界的条件来选择行动。一定程度上,该条件会因行动者的操作而发生改变,改变后的条件就是控制行动的一种方式。正如工程师所知,具有反馈功能的调节系统有着强大的控制能力。

第三,TOTE明确了纳入停止规则的重要性,该规则决定何时停止做某件事,以便控制能够顺着一个又一个的TOTE传递下去。如我们所见,确定停止条件然后停止该动作,无论是通过阻止动作还是将控制权移交给一个新的行动,都是大脑控制系统的重要特征。

第四,TOTE可以相互嵌入,从而形成控制的层次结构。为了说明这一点,在我们的TOTE示例中,可以将“吃香蕉”的行动阶段本身分解为咬、咀嚼和吞咽香蕉的子TOTE,从而控制吃掉一只香蕉的流程。

图1.2C以此方式详尽地描绘了吃香蕉的TOTE示例。当然,我们还可以将这些子TOTE行动步骤进一步细化为子—子TOTE。例如,图1.2C中的咀嚼行动可以细化为两个二级下颌控制TOTE之间的流程,第一个二级TOTE打开闭合的(测试显示)下颌,第二个二级TOTE关闭张开的(测试显示)下颌。

这种能够对结构进行分层的能力意味着我们可以持续地细化控制流程。将每个TOTE的行动阶段细化为另一个二级TOTE,二级TOTE本身可以在其行动过程中嵌入另外的三级TOTE。这样,控制流程在细节层次上变得越来越精细。

TOTE的层次结构与动作本身的层次结构一致。任何指定的任务都可以描绘为多个抽象层次。例如,我早上煮咖啡的常规顺序大致为:往研磨机里装满咖啡豆,打开研磨机,往玻璃水瓶里装满水,把水倒入蓄水壶,将磨好的咖啡粉放入过滤器,打开咖啡滴滤机,等待。其中每一个动作都可以进一步分解。例如,“将磨好的咖啡粉放进过滤器”包括从橱柜中取出咖啡过滤纸,展开滤纸,往研磨机上铺滤纸,等等。这些子—子任务本身可以分解成子—子—子任务,最终形成一套有着特定顺序的动作。因此,层次控制行为的能力是任何控制系统的必要特性。

图1.2 米勒、加兰特、普里布拉姆的测试—操作—测试—退出(TOTE)结构示意图。(A)带箭头的TOTE基本结构,显示从“测试—操作”再到“测试—退出”的控制流程。(B)TOTE简例——吃香蕉。(C)吃香蕉的TOTE控制流程分层结构详细说明。现在,行动符“吃香蕉”由三个子TOTE之间的流程来呈现。位于中间的子TOTE——咀嚼行动符——进一步细分为控制下颌的两个子—子TOTE。

第五,像TOTE这样的层次控制结构证明,我们具体制订的计划越精细,监控级别就越高。即使在简单的吃香蕉示例中,这一点也显而易见,只要数数图1.2B和1.2C中的测试及其对应的操作的数量就知道了。TOTE层次越多,添加测试的频率就越比操作的高。这是因为每嵌入一个子任务时,我们都会添加一次新测试,替换掉要执行的操作。因此,计划一个行为越深入细致,对管理、跟踪和执行的测试的要求就越高。这也与我们的认知控制系统相似,认知控制常需要设置合适的测试条件来控制执行什么操作以及什么时候执行该操作。