
고려하다
\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
a 와 "동등"하며 최대 15개 레벨까지 \input
가능합니다 .\input
질문:
- 왜?꼬리 재귀 제거입력이 토큰 목록 대신 라인에서 오는 경우 작동하지 않습니까?
- 문제를 해결하는 방법? 예를 들어
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. 퓨처렛을 사용하세요
%! 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
확장 전용 컨텍스트에서 작동하도록 만드는 데 사용됩니다.
다음 토큰이 notexpanded
토큰이면 변경된다는 점에 유의하세요.
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].