Имя переменной цикла @for печатается вместо содержимого в среде табуляции

Имя переменной цикла @for печатается вместо содержимого в среде табуляции

Я пытаюсь автоматически сгенерировать несколько строк с отступом, используя tabbingокружение и @forцикл. По какой-то причине это приводит к тому, что цикл for снова и снова печатает имя переменной итерации вместо ее содержимого. Что я делаю не так?

МВЭ:

\documentclass{article}
\begin{document}
\begin{tabbing}
a \= b\\
\> c\\
\makeatletter
\@for\ij:=abc,def\do{\>\ij{}\\}
\makeatother
\end{tabbing}
\end{document}

решение1

Ячейки таблицы создают группы, поэтому любое неглобальное назначение теряется, когда TeX переходит в другую ячейку (здесь, когда вы используете \>для перехода к следующему столбцу или \\к следующей строке). \@forвыполняет локальное назначение переменной цикла, поэтому оно естественным образом теряется, когда ячейка таблицы заканчивается. Вы видите, что «имя» переменной цикла печатается, потому что вы выбрали \ij, стандартное определение которого печатает голландский диграф «ij». Если бы вы использовали \ii(или что-то не определенное), вы бы получили ошибку.

Если переменная цикла — это самое первое, что следует после \>, вы можете схитрить и расширить переменную цикла до того, как ячейка таблицы закончится на \expandafter. Это не сработает (без адаптации), если перед переменной цикла есть что-то еще:

\@for\ii:=abc,def\do{\expandafter\>\ii{}\\}

Вы также можете присвоить значение глобальной переменной до завершения ячейки таблицы, после чего глобальная переменная может появиться в любом месте.

\@for\ii:=abc,def\do{\global\let\jj=\ii  \> something \jj{}\\}

Но я бы рекомендовал использовать функцию цикла, которая не использует переменную цикла. Например, expl3's \clist_map_inline:nn(здесь переименовано в \ListLoop):

\documentclass{article}
\ExplSyntaxOn
\cs_new_eq:NN \ListLoop \clist_map_inline:nn
\ExplSyntaxOff
\begin{document}
\begin{tabbing}
a \= b\\
\> c\\
\ListLoop{abc,def}{\>#1\\}
\end{tabbing}
\end{document}

Первый аргумент — это список для итерации, а второй — код, который будет выполняться на каждой итерации, в котором #1находится текущий элемент (или ##1тот, который вы используете \ListLoopвнутри определения).

Связанный контент