scan 是一种迭代操作,它与 map 的关系类似于 do 和 table 之间的对应关系,相信你很容易领会。通常人们误以为 scan 完全不返回任何结果,但严格来说,它并非真正“无返回”。与 do 类似,scan 实际上会返回一个值——即 null,也就是空值。因此,尽管表面上没有可见输出,实际上仍以 null 作为其执行结果进行传递。
1、 观察其语法形式,你会发现它与 Map 几乎完全一致。

2、 Scan 不支持简写形式,必须完整写出其标准语法结构。如下图所示,可将 Map 与 Scan 并列使用以作对比。特别需要注意的是,Scan 的最终返回值恒为 Null。

3、 为何需要 Scan 这类迭代指令?其设计初衷与 Do 非常相似。在某些循环任务中,我们并不关心每次函数调用产生的返回值,而只关注操作本身的执行过程。例如前面提到的实际应用:对一组图像文件逐个生成缩略图。该任务的关键在于调用 Export 函数完成保存动作,而非获取其返回的文件路径字符串。此时,Do 已能满足基本需求;但如果追求更高性能,Scan 则是更优解。虽然 Scan 和 Map 都用于对集合中的每个元素施加函数,但二者存在根本性差异:Map 会汇总所有调用结果并构造出新列表;而 Scan 则彻底忽略返回值,专用于触发副作用(如写入文件、更新变量等),因此在无需收集结果时效率更高。通过对比两者的执行流程,可以更直观地把握它们各自的适用场合:当仅需驱动操作而不依赖中间或最终结果时,Scan 显得尤为合适。

4、 如果只想提取循环过程中某些特定步骤的计算结果,则需要借助数据采集机制。还记得 Sow 和 Reap 的协同工作方式吗?之前在 Do 中演示过的例子,现在改用 Scan 来重写,不仅代码更简洁,执行也更高效,同时依然能精准捕获所需的中间值,适用于各类需要筛选性记录的迭代场景。

5、 在 Mathematica 中,一切皆为表达式,而每个表达式都可被视作一棵树形结构。和 Map 一样,Scan 同样遵循标准的深度优先遍历规则,能够递归访问表达式的各个组成部分。利用这一特性,我们可以轻松扫描复杂表达式的内部节点。以下示例展示了如何遍历一个 Graphics 表达式,并提取其中所有的叶子节点——即处于最底层、不可再分解的基本单元,从而深入理解其组织结构与嵌套层次。












