我无法理解 TeX 宏的扩展顺序:
\newcount\x
\def\dec#1{%
\ifnum#1=0
.%
\else
#1%
\x=#1
\advance\x by-1
\dec{\number\x}%
#1%
\fi%
}
\dec{5}
\bye
上面的非尾递归结果是54321.00005
,而不是。我明白我想要的可以通过在递归扩展后54321.12345
恢复来实现。但是,我不太明白为什么这会导致。\x
\dec
00005
有人能告诉我吗?谢谢。
答案1
\newcount\x
\def\dec#1{%
\ifnum#1=0
.%
\else
#1%
\x=#1
\advance\x by-1
\dec{\number\x}%
#1%
\fi%
}
{\tracingmacros1 \tracingonline1
\dec{5}
}
\bye
生产
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \dec {\number \x }#1\fi
#1<-5
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \dec {\number \x }#1\fi
#1<-\number \x
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \dec {\number \x }#1\fi
#1<-\number \x
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \dec {\number \x }#1\fi
#1<-\number \x
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \dec {\number \x }#1\fi
#1<-\number \x
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \dec {\number \x }#1\fi
#1<-\number \x
所以你会看到你每次都没有传递不同的值,每个参数都是\number \x
如此,最后你有多个,\number\x
所以它们都打印 0
你可以\number
在递归之前进行扩展
\newcount\x
\def\dec#1{%
\ifnum#1=0
.%
\else
#1%
\x=#1
\advance\x by-1
\expandafter\dec\expandafter{\number\x}%
#1%
\fi%
}
{\tracingmacros1 \tracingonline1
\dec{5}
}
\bye
生产
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \expandafter \dec \expand
after {\number \x }#1\fi
#1<-5
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \expandafter \dec \expand
after {\number \x }#1\fi
#1<-4
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \expandafter \dec \expand
after {\number \x }#1\fi
#1<-3
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \expandafter \dec \expand
after {\number \x }#1\fi
#1<-2
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \expandafter \dec \expand
after {\number \x }#1\fi
#1<-1
\dec #1->\ifnum #1=0 .\else #1\x =#1 \advance \x by-1 \expandafter \dec \expand
after {\number \x }#1\fi
#1<-0
使用 etex (包括 pdftex、luatex、xetex 等) 您不需要\x
\def\dec#1{%
\ifnum#1=0
.%
\else
#1%
\expandafter\dec\expandafter{\number\numexpr#1-1\relax}%
#1%
\fi%
}
{\tracingmacros1 \tracingonline1
\dec{5}
}
\bye
答案2
通过 TeX的 -branch#1
中的最后一个,内存中会累积 token,而不是求值的结果(每次迭代都会产生另一个结果)。当最后一次迭代后对所有累积进行求值时,的值为0。\else
\dec
\number\x
\number\x
\number\x
\x
为了更清楚地了解正在发生的事情,让我们通过\expandafter
and \number
before 来评估参数\exchange
,并将评估结果放在分支的末尾\else
/关闭之前\fi
:
\newcount\x
\long\def\exchange#1#2{#2#1}
\def\dec#1{%
\ifnum#1=0
.%
\else
#1%
\expandafter\exchange\expandafter{\number#1}{%
\x=#1
\advance\x by-1
\dec{\number\x}%
}%
\fi%
}
\dec{5}
\bye
此代码仅用于展示问题代码存在什么问题。
对于实际用途来说,David Carlisle 在他的回答中提供的代码要好得多。