
Я использую etoolbox
для обработки списков, в частности \forcsvlist
.
При передаче списка, разделенного запятыми, напрямую в \forcsvlist
, он может разобрать каждый элемент в списке. Однако, если я определяю переменную списка где-то еще, он \forcsvlist
не может различать каждый элемент в списке и воспринимает его как один целый аргумент.
Например:
\newcommand\doforme[1]{#1 \\}
\forcsvlist\doforme{a,b,c}
Вышеуказанный код отлично работает, добавляя новую строку в конец каждого элемента. Но следующий код не работает
\newcommand\doforme[1]{#1 \\}
\def\@authors{a,b,c}
\forcsvlist\doforme{\@authors}
Это заставляет меня думать, что должен быть какой-то другой способ определения списка, который \forcsvlist
можно интерпретировать.
решение1
Проблема использования переменной формы заключалась в ее более раннем расширении, которое затем принимало все a,b,c
как одну сущность. Под одной сущностью я подразумеваю единственный элемент в списке.
Чтобы решить эту проблему, прежде всего нам нужно использовать здесь двойные скобки. Так что {a,b,c}
становится {{a,b,c}}
, причина чего станет ясна к концу этого ответа.
\expandafter
примитив расширяет аргумент, данный ему после следующего. Например, если есть \def\foo{A}, \def\bar{B}
и \expandafter\foo\bar
, он сначала станет \foo B
, а затем в конечном итоге станет AB
.
Аналогично я могу решить вышеуказанную проблему в вопросе следующим образом:
noindent\expandafter\forcsvlist\expandafter\doforme\authors
Если мы посмотрим на рекурсивное выражение выше, то первое expandafter переходит к своему первому аргументу (\forcsvlist), пропускает его на некоторое время и пытается расширить аргумент рядом с ним, который в этом случае снова \expandafter
. Итак, второе \expandafter
снова пропускает \doforme
на некоторое время, а затем расширяется \authors.
\authors
is current {{a,b,c}}
. После расширения оно становится {a,b,c}
. Таким образом, окончательное выражение теперь становится
\noident\forcsvlist\doforme{a,b,c}
что эквивалентно передаче аргумента, как в первом случае в вопросе, и, следовательно, приводит к тем же результатам.
решение2
Пакет etoolbox
определяет специальную команду для обработки внутренних списков: \forlistloop
. Эти списки используют специальный символ в качестве внутреннего разделителя списка. Поэтому вам придется использовать \listadd
(или аналогичные команды - см.etoolbox
документация) для добавления элемента в такой список.
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\newcommand\doforme[1]{#1 \\}
\forcsvlist{\listadd\authors}{a,b,c}
\noindent\forlistloop\doforme{\authors}
\end{document}