在制定另一个SO问题的答案时,我在Mathematica中遇到了一些关于尾递归的奇怪行为.
在数学文档暗示,尾调用优化的可能被执行.但我自己的实验给出了相互矛盾的结果.对比,例如,以下两个表达式.第一个崩溃7.0.1内核,可能是由于堆栈耗尽:
(* warning: crashes the kernel! *)
Module[{f, n = 0},
f[x_] := (n += 1; f[x + 1]);
TimeConstrained[Block[{$RecursionLimit = Infinity}, f[0]], 300, n]
]
Run Code Online (Sandbox Code Playgroud)
第二个运行完成,似乎利用尾调用优化来返回有意义的结果:
Module[{f, n = 0},
f[x_] := Null /; (n += 1; False);
f[x_] := f[x + 1];
TimeConstrained[Block[{$IterationLimit = Infinity}, f[0]], 300, n]
]
Run Code Online (Sandbox Code Playgroud)
两个表达式都定义了尾递归函数f.在第一个函数的情况下,Mathematica显然认为复合语句的存在足以击败尾调用优化的任何机会.还要注意,第一个表达式由$RecursionLimit第二个表达式控制,第二个表达式由$IterationLimitMathematica以不同方式处理这两个表达式.(注意:上面提到的SO答案有一个较少设法的功能,成功利用尾部调用优化).
所以,问题是:有没有人知道Mathematica对递归函数进行尾调用优化的情况?在Mathematica文档或其他WRI材料中提及最终陈述将是理想的.投机也很受欢迎.
recursion wolfram-mathematica tail-recursion tail-call-optimization
美好的一天,
我说,我有一些非常懒散和复杂的功能f[x,y].我需要详细ContourPlot介绍它.此外,f[x,y]由于缺乏物理内存,该功能有时会失败.在这种情况下,我必须自己停止评估并调查点{x,y}的问题情况.然后我应该将元素{x,y,f [x,y]}添加到计算值列表f[x,y](比如"缓存")并重新开始评估ContourPlot.ContourPlot必须f从缓存中获取所有已计算的值.我宁愿将这样的列表存储在某个文件中,以便以后能够重用它.并且手动向该文件添加有问题的点可能更简单.
如果计算值列表f可能包含10000-50000个点,那么实现此方法的最快方法是什么?
f[0] = 0;
f[1] = 1;
f[x_] := f[x-1] + f[x-2]
Run Code Online (Sandbox Code Playgroud)
这个功能在Mathematica中运行缓慢,我需要提高速度.我必须使用函数式编程和递归.我不确定为什么这么慢,甚至最轻微的想法如何改善这将是有帮助的.