在制定另一个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
在对另一个SO问题的回答中,提到了Mathematica字符串转义语法,如下所示:"\<...\>".显然,这种语法对于处理字符串中的嵌入换行非常有用.我尝试使用Mathematica帮助浏览器(和Google)中的各种术语搜索文档,但无济于事.我在哪里可以找到有关此语法的文档?
答案摘要
@Mark指出该构造在V5 Mathematica书的第2.8.6节中有记载.它也在V5.2 Mathematica Book的2.8.7节中提到过.在这两个位置中,文档都指出Mathematica忽略换行符并跟随字符串中的制表符 - 除非它们被包含在其中\<并且\>在这种情况下保留换行符(但不是制表符).
在V6文档的相应部分中,它指出换行符保留在字符串中.因此,似乎从V6开始不再需要转义语法 - 因此不再记录.
请注意,即使在V8中,许多笔记本仍在内部使用此语法.@Alexey指出包含换行符的字符串的单元格表达式仍然使用语法.
如何将从单元格表达式中提取的任意框规范转换为输入表达式?
这是我在FullForm语法中对Save Mathematica代码的回答.在该上下文中,模式匹配被用于从使用读取的笔记本表达式中提取框规范Import.
我认为ToExpression或者MakeExpression会做盒子解释的工作,但在某些情况下他们没有.
考虑一个包含表达式的输入单元格:
StringForm["a = ``", 1]
Run Code Online (Sandbox Code Playgroud)
这种细胞的细胞表达如下:
Cell[BoxData[
RowBox[{"StringForm", "[",
RowBox[{"\"\<a = ``\>\"", ",", " ", "1"}], "]"}]], "Input"]
Run Code Online (Sandbox Code Playgroud)
我可以BoxData从这个单元格ToExpression中获取子表达式并使用获取相同的输出,就像我评估原始单元格一样:
ToExpression @
BoxData[
RowBox[{"StringForm", "[",
RowBox[{"\"\<a = ``\>\"", ",", " ", "1"}], "]"}]]
Run Code Online (Sandbox Code Playgroud)
但现在考虑以下输入表达式:
StringForm["a = ``", 1]
你必须仔细观察才能发现差异:a用斜体字表示.这是相应的单元格表达式:
Cell[BoxData[
RowBox[{"StringForm", "[",
RowBox[{"\"\<\!\(\*
StyleBox[\"a\",
FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]], "Input"]
Run Code Online (Sandbox Code Playgroud)
如果我正常评估这个单元格,我会得到预期的结果.但是,如果我尝试应用ToExpression到BoxData像以前一样的子表达式: …