让我们一步一步来评估flog[1, 2]
...
鞭打[1, 2]
当计算此表达式时,Mathematica 将替换问题中给出的定义中的1
forx
和2
for 。这产生了我们游览的下一步:y
flog
flog[1, 2] = f[1, 2] /。v_ :> (PutAppend[未评估[flog[1, 2] = v;], $runningLogFile]; v)
请注意,这里的赋值flog[1, 2] = ...
, 是其flog
自身定义的一部分。
/.
是一个中缀运算符,它是ReplaceAll函数的替代表示。 ReplaceAll
将对第一个参数的值应用替换规则。保持这个想法 - 我们会回到它。第一个论点是flog[1, 2] = f[1, 2]
。此表达式将评估f[1, 2]
然后将结果分配给flog[1, 2]
. 为了便于讨论,我们假设f[1, 2]
返回345
。因此,一个新的定义将被添加到flog
,即flog[1, 2] = 345
。赋值后,我们可以检查 的定义flog
:
观察 whereflog
最初只有一个定义,但现在它有两个 - 新添加flog[1, 2]
的定义缓存了该调用的结果。这通常被称为“记忆”。
flog[1, 2] = 345
可能会有为 建立新定义的副作用,flog
但是,就像 Mathematica 中的每个表达式一样,它也产生一个值。经过一番折腾后,该值345
将成为ReplaceAll
.
to 的第二个参数ReplaceAll
是运算符的调用,是RuleDelayed函数:>
的中缀表达式。为了将这篇文章保持在可管理的大小,我们将简单地注意到规则在这种情况下对自身进行评估。
所以,现在我们有一个涉及/.
评估的表达式......
345 /。v_ :> (PutAppend[未评估[flog[1, 2] = v;], $runningLogFile]; v
替换表达式将其第一个参数 ( 345
) 与替换规则 ( v_
) 的模式组件相匹配。 v_
匹配345
(或与此相关的任何其他内容)并给出345
名称v
以用于替换。 ReplaceAll
然后替换规则右侧345
的每个出现。v
结果是要评估的下一个表达式...
(PutAppend[未评估[flog[1, 2] = 345;], $runningLogFile]; 345)
这里我们有两个用分号分隔的表达式。顺便说一下,;
是一个扩展为CompoundExpression的中缀运算符。第一个表达式涉及PutAppend,它将其第一个参数的值写入名为第二个参数值的文件。但是请注意,第一个参数包含在Unevaluated中。这会抑制对第一个参数的评估,以便将其完全按原样写入文件:flog[1, 2] = 345;
. 如果当前 Mathematica 会话结束,书面表达式可以读入未来的 Mathematica 会话,以重新建立记忆的结果flog[1, 2]
。
CompoundExpression
丢弃除最后一个以外的所有参数的值。在这里,最后一个参数是345
。由于我们已经到了表达式的结尾,这将是原始调用的最终返回值。也就是说,flog[1, 2]
返回345
——尽管正如我们所见,有一些副作用将这个结果保存到内存和磁盘中以供将来参考。
未来的呼吁flog[1, 2]
现在如果flog[1, 2]
再次调用,Mathematica 将找到新定义flog[1, 2] = 345
。 345
将直接退回,没有我们上面讨论的任何并发症。特别是,它甚至不会f[1, 2]
再次调用。当然,这就是这个例子的全部动机。假设f
计算起来非常昂贵,证明所有这些体操都是为了尽量减少计算发生的次数。