Skip to content

Commit 3b93de3

Browse files
committed
[list] tail-call
1 parent ae04185 commit 3b93de3

File tree

1 file changed

+14
-28
lines changed

1 file changed

+14
-28
lines changed

others/appendix/list/list-zh-cn.tex

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,19 +1126,16 @@ \subsubsection{尾递归}
11261126
\index{Tail call}
11271127
\index{Tail recursion}
11281128
\index{Tail recursive call}
1129-
Note that both sum and product algorithms actually compute the result from right to left. We can change them
1130-
to the normal way, that calculate the {\em accumulated} result from left to right. For example with sum,
1131-
the result is actually accumulated from 0, and adds element one by one to this accumulated result till
1132-
all the list is consumed. Such approach can be described as the following.
11331129

1134-
When accumulate result of a list by summing:
1130+
注意到无论是求和还是求积的算法都从右向左计算。我们可以修改它们的实现,从左向右\underline{累积计算}结果。求和时,结果从0开始累积,逐一将每个元素加到结果上,直到处理完全部列表。具体描述如下:
1131+
1132+
当通过求和累积结果时:
11351133
\begin{itemize}
1136-
\item If the list is empty, we are done and return the accumulated result;
1137-
\item Otherwise, we take the first element from the list, accumulate it to the result by summing, and go on
1138-
processing the rest of the list.
1134+
\item 若列表为空,则累积结束,返回累积结果;
1135+
\item 否则,取出列表中的第一个元素,将其加到累积结果上,然后继续处理剩余的列表。
11391136
\end{itemize}
11401137

1141-
Formalize this idea to equation yields another version of sum algorithm.
1138+
将这一描述形式化为定义,就可以得到另一种累加的算法。
11421139

11431140
\be
11441141
sum'(A, L) = \left \{
@@ -1150,25 +1147,16 @@ \subsubsection{尾递归}
11501147
\right.
11511148
\ee
11521149

1153-
And sum can be implemented by calling this function by passing start value 0 and the list as arguments.
1150+
最终求和可以通过调用这一函数实现。我们传入0作为累加的起始值,同时传入待累加的列表。
11541151
\be
11551152
sum(L) = sum'(0, L)
11561153
\ee
11571154

1158-
The interesting point of this approach is that, besides it calculates the result in a normal order from
1159-
left to right; by observing the equation of $sum'(A, L)$, we found it needn't remember any intermediate
1160-
results or states when perform recursion. All such states are either passed as arguments ($A$ for example)
1161-
or can be dropped (previous elements of the list for example). So in a practical implementation,
1162-
such kind of recursive function can be optimized by eliminating the recursion at all.
1155+
这一改进除了将计算的顺序恢复为从左向右之外,还有一个重要的特点。观察函数$sum'(A, L)$的定义,我们发现它无需记录任何中间结果或者状态用于递归。所有的状态或者作为参数(例如$A$)传入接下来的递归调用,或者可以丢弃(例如列表中前面处理过的元素)。因此在实际的实现中,这样的递归函数可以进一步优化为循环,从而完全消除递归。
11631156

1164-
We call such kind of function as `tail recursion' (or `tail call'), and the optimization of removing recursion in this case as
1165-
'tail recursion optimization'\cite{wiki-tail-call} because the recursion happens as the final action
1166-
in such function. The advantage of tail recursion optimization is that the performance can be greatly
1167-
improved, so that we can avoid the issue of stack overflow in deep recursion algorithms such as sum and
1168-
product.
1157+
我们称这样的函数为“尾递归”(或“尾调用”),对其消除递归的优化称为“尾递归优化”\cite{wiki-tail-call}。顾名思义,这类函数中,递归发生在最后一步。尾递归优化可以极大地提高性能,并避免由于过深递归造成的调用栈溢出。
11691158

1170-
Changing the sum and product Haskell programs to tail-recursion manner gives the following modified
1171-
programs.
1159+
下面的Haskell例子程序给出了尾递归形式的求和与求积实现。
11721160

11731161
\lstset{language=Haskell}
11741162
\begin{lstlisting}
@@ -1181,8 +1169,7 @@ \subsubsection{尾递归}
11811169
product' acc (x:xs) = product' (acc * x) xs
11821170
\end{lstlisting}
11831171

1184-
In previous section about insertion sort, we mentioned that the functional version sorts the elements
1185-
form right, this can also be modified to tail recursive realization.
1172+
在前面关于插入排序的部分,我们提到了函数式的实现从右向左对元素排序,我们也可以将其改为尾递归的形式。
11861173

11871174
\be
11881175
sort'(A, L) = \left \{
@@ -1194,15 +1181,14 @@ \subsubsection{尾递归}
11941181
\right.
11951182
\ee
11961183

1197-
The the sorting algorithm is just calling this function by passing empty list as the accumulator argument.
1184+
排序时,我们可以调用这一函数,传入一个空列表作为累积结果的起始值。
11981185
\be
11991186
sort(L) = sort'(\phi, L)
12001187
\ee
12011188

1202-
Implementing this tail recursive algorithm to real program is left as exercise to the reader.
1189+
我们将它的具体实现作为练习留给读者。
12031190

1204-
As the end of this sub-section, let's consider an interesting problem, that how to design an algorithm
1205-
to compute $b^n$ effectively? (refer to problem 1.16 in \cite{SICP}.)
1191+
作为本节的结尾,我们考虑一个有趣的题目,如何设计一个算法来高效地计算$b^n$?(参考\cite{SICP}中的1.16节。)
12061192

12071193
A naive brute-force solution is to repeatedly multiply $b$ for $n$ times from 1, which leads to a
12081194
linear $O(n)$ algorithm.

0 commit comments

Comments
 (0)