
Я хочу определить макрос, который передает свое содержимое в \foreach
оператор tikz, например:
\newcommand\Macro[1]{ \foreach \x in {#1} {x=\x.} }
который затем используется как \Macro{1,2,3,4}
. Иногда я хочу дать ему "пустые" аргументы, например \Macro{,,,4,5,5}
. Я хотел бы иметь возможность определять "пустые" аргументы и делать что-то другое в таких случаях. Я думал, что сработает что-то вроде следующего:
\newcommand\Macro[1]{%
\foreach \x in {#1} {
\if\relax\detokenize{\x}\relax Empty!
\else x=\x.
\fi
}
}
но по какой-то причине это не обнаруживает пустые аргументы и вместо этого выдает:
Я перепробовал много других вариантов, например, \x
сначала расширение, но пока ничего не сработало.
Может ли кто-нибудь увидеть способ сделать это?
[Мой реальный код генерирует tikzpicture
среду, поэтому я действительно хочу использовать \foreach
`tikz.]
решение1
решение2
Проблема в макросе из вопроса:
\newcommand\Macro[1]{%
\foreach \x in {#1} {
\if\relax\detokenize{\x}\relax Empty!
\else x=\x.
\fi
}
}
это то, что \detokenize
не расширяет свой аргумент и возвращает два токена \
и x
. Это лечится добавлением \expandafter
:
\detokenize\expandafter{\x}
Полный макрос:
\newcommand\Macro[1]{%
\foreach \x in {#1} {
\if\relax\detokenize\expandafter{\x}\relax Empty!
\else x=\x.
\fi
}
}
решение3
Обязательный expl3
ответ (после того, как \detokenize\expandafter{\x}
будет отмечено, что это и есть решение):
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\blankTF}{mmm}
{% #1 = text to test, #2 = blank case, #3 = non blank case
\str_if_eq_x:nnTF { #1 } { } { #2 } { #3 }
}
\NewDocumentCommand{\lforeach}{O{,}mm}
{% #1 = delimiter, #2 = list, #3 = code
\seq_set_split:Nnn \l_andrew_foreach_seq { #1 } { #2 }
\seq_map_inline:Nn \l_andrew_foreach_seq { #3 }
}
\ExplSyntaxOff
\newcommand\Macro[1]{%
\lforeach{#1}{%
\blankTF{##1}{Empty!}{$|$##1$|$.}
}
}
\begin{document}
\lforeach[-]{a-b--\texttt{c}}{%
\blankTF{#1}{Empty!}{$|$#1$|$.}
}
\lforeach{, ,,4, 5 ,5}{%
\blankTF{#1}{Empty!}{$|$#1$|$.}
}
\Macro{, ,,4, 5 ,5}
\end{document}
Текущий элемент в цикле обозначается #1
(который должен стать ##1
в определении \Macro
).