
Considerar
\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}
Problema:
TeX capacity exceeded, sorry [text input levels=15].
Por lo que puedo ver tex.sprint
es "equivalente" a un \input
que contiene el contenido impreso, y puedes tener \input
15 niveles como máximo.
Pregunta:
- ¿Por qué eleliminación de recursividad de cola¿No funciona cuando la entrada proviene de una línea en lugar de una lista de tokens?
- ¿Cómo solucionar el problema? Suponiendo que necesito
tex.sprint()
, por ejemplo, imprimir más contenido de cadena a la derecha de\F
.
Mientras tanto, encuentro una solución usando token.put_next()
, pongo \relax y la obtengo más tarde.
Respuesta1
Puede forzar a tex a desenrollar la pila de entrada antes de recurrir mirando hacia adelante con\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}
Respuesta2
0.texio.closeinput()
Sugerido porun comentario
Código:
%! 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}
El manual explica...
Esta función debe usarse con cuidado. Actúa como \endinput pero al final de Lua. Puedes usarlo para (más o menos) forzar un salto de regreso a TeX.
lo que significa que elimina el contenido restante del "archivo" superior.
Nota/aclaración del manual,
- no lo haceen realidadVuelva a TeX, el siguiente contenido de Lua aún se ejecuta
tex.print()
Los comandos que lo preceden también se eliminan.- a diferencia
\endinput
del siguiente contenido en la línea se elimina - peroSi hay algunos tokens pendientes,
token.put_next()
se conservarán tanto tiempo como los posteriores. - sólo se aplica al "archivo"/pseudoarchivo real en lugar de, por ejemplo, la lista de tokens de argumentos
1. Utilice token.put_next en el token de continuación.
%! 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}
(experimentalmente, todo token.put_next()
viene después de todo tex.*print()
, independientemente de su orden en el código)
Creo que la razón por la que este método funciona es que mientras se expande una macro, a diferencia de cuando se ejecuta token.get_next()
o token.scan_toks()
etc., TeX desenrolla la pila de entrada (incluso en caso de que la macro no tenga ningún argumento, como en este caso)
2. Utilice futuro
%! 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
solía hacerlo funcionar en un contexto de solo expansión.
Tenga en cuenta que si el siguiente token es un notexpanded
token, se cambiará.
3. (solo funciona parcialmente, no lo use) Use token.put_next en otro token y get_next desde dentro de Lua
%! 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}
Esto no realiza una recursividad de cola adecuada (de alguna manera token.get_next()
no elimina el nivel de entrada si está agotado), por lo que si 3000 aumenta a un valor mayor, verá
TeX capacity exceeded, sorry [input stack size=5000].