如果规范在某一处匹配失败,并不一定意味着会报语法错误; 相反,会发生 回溯(backtracking),直到所有候选项都尝试完毕。 最终,参数列表中的每一个元素都必须被规范中的某个元素匹配, 且规范中所有必选元素都必须匹配到某个参数。
当检测到语法错误时,可能要等到很久之后才会报告——
即在更上层的候选项都耗尽之后,此时光标位置也已经远离真正的错误位置。
但如果在错误发生时禁用回溯,就可以立即报告错误。
注意,在以下几种情况下回溯会被自动重新启用:
当通过 &optional、&rest 或 &or 建立新的候选项时,
或是开始处理子列表、分组、间接规范时。
启用或禁用回溯的效果,仅限于当前正在处理的层级的剩余部分以及更低层级。
在匹配任何表达式类规范(即 form、body、def-form 和 def-body)时,回溯会被禁用。
这些规范可以匹配任意表达式,因此任何错误一定出在表达式本身,而不在更高层级。
在成功匹配带引号的符号、字符串规范或 &define 关键字之后,回溯也会被禁用,
因为这通常表示已经匹配到一个可识别的结构。
但如果你有多组候选项结构都以同一个符号开头,
通常可以将该符号从候选项中提取出来以绕过这一限制,例如:
["foo" &or [first case] [second case] ...]。
这两种自动禁用回溯的方式可以满足大多数需求,
但偶尔使用 gate 规范显式禁用回溯会很有用。
当你确定更高层不会再有其他候选项可以匹配时,这就非常实用。
参见 let 规范的示例。