
考慮
\documentclass[12pt]{article}
\usepackage{luacode}
%\usepackage{luacr}
%\usepackage{miscellaneous}
\begin{document}
\global\def\F{\directlua{f()}}
\begin{luacode*}
i=0
function f()
if i<30 then
i=i+1
tex.sprint(i .. [[, \F]])
end
end
\end{luacode*}
\F
\end{document}
問題:
TeX capacity exceeded, sorry [text input levels=15].
據我所知,tex.sprint
「相當於」\input
包含印刷內容的a,\input
最多可以有15個等級。
問題:
- 為什麼尾遞迴消除當輸入來自一行而不是標記列表時不起作用?
- 如何解決這個問題?假設我需要
tex.sprint()
在 的右側列印更多字串內容\F
。
同時,我找到了一個解決方法,使用token.put_next()
,放置一個 \relax 並稍後獲取它。
答案1
您可以透過向前查看來強制 tex 在遞歸之前展開輸入堆疊\expandafter
\documentclass[12pt]{article}
%\usepackage{luacr}
%\usepackage{miscellaneous}
\begin{document}
\def\F{\expanded{\noexpand\directlua{f()}\expandafter}}
\directlua{
i=0
function f()
if i<30 then
i=i+1
tex.sprint(i .. [[, \string\F]])
end
end
}
\F
\end{document}
答案2
0。texio.closeinput()
建議來自一則評論
代碼:
%! TEX program = lualatex
\documentclass[12pt]{article}
\usepackage{luacode}
\begin{document}
\def\F{\directlua{f()}}
\begin{luacode*}
i=0
function f()
if i~=0 then
texio.closeinput()
end
if i<20000 then
i=i+1
tex.sprint(i .. [[, \F]])
end
end
\end{luacode*}
\F
\end{document}
手冊解釋...
此功能應謹慎使用。它充當 \endinput 但位於 Lua 端。您可以使用它(某種程度上)強制跳轉回 TeX。
這意味著它會刪除最頂層「檔案」的剩餘內容。
手冊的註釋/說明,
- 事實並非如此真的跳回TeX,依然執行下面的Lua內容
tex.print()
前面的命令也被刪除- 不像
\endinput
下面的內容就行被丟棄 - 但如果有一些待處理的代幣,
token.put_next()
它們將與之後的代幣一樣保留 - 僅適用於真實的“文件”/偽文件,而不是例如參數標記列表
1. 在延續令牌上使用 token.put_next
%! TEX program = lualatex
\documentclass[12pt]{article}
\usepackage{luacode}
\begin{document}
\def\F{\directlua{f()}}
\begin{luacode*}
i=0
function f()
if i<20000 then
i=i+1
tex.sprint(i .. [[, ]])
token.put_next(token.create("F"))
end
end
\end{luacode*}
\F
\end{document}
(實驗上,不管它們在程式碼中的順序如何,token.put_next()
畢竟都是來的)tex.*print()
我認為這個方法起作用的原因是,在擴展巨集時,與執行token.get_next()
或token.scan_toks()
等時不同,TeX 展開輸入堆疊(即使巨集沒有任何參數,例如在本例中)
2.使用futurelet
%! TEX program = lualatex
\documentclass[12pt]{article}
\usepackage{luacode}
%\usepackage{miscellaneous}
%\tracingmacros=1
\begin{document}
\def\F{\directlua{f()}}
\begin{luacode*}
i=0
function f()
if i<20000 then
i=i+1
tex.sprint(i .. [[, \immediateassignment\futurelet\a\F]])
end
end
\end{luacode*}
\expanded{\F}
\end{document}
\immediateassignment
用於使其在僅擴展上下文中工作。
注意,如果後面的token是notexpanded
token,那麼它會被改變。
3.(僅部分有效,請勿使用)在另一個令牌上使用 token.put_next 並從 Lua 內部對其進行 get_next
%! TEX program = lualatex
\documentclass[12pt]{article}
\usepackage{luacode}
%\usepackage{miscellaneous}
%\tracingmacros=1
\begin{document}
\def\F{\directlua{f()}}
\begin{luacode*}
i=0
function f()
token.get_next() -- the relax token, either the original one or result of put_next
if i<3000 then
i=i+1
tex.sprint(i .. [[, \F]])
token.put_next(token.create("relax"))
end
end
\end{luacode*}
\F\relax
\end{document}
這不會執行正確的尾遞歸(token.get_next()
如果輸入等級耗盡,則不會以某種方式消除輸入等級),因此如果 3000 增加到更大的值,您將看到
TeX capacity exceeded, sorry [input stack size=5000].