我希望这个问题有意义。如果我想修改以下代码以允许用户传递宏作为第一个参数,我该怎么做?
情况是这样的:
(使用pgf
)
\def\appendtolist#1{% <item>
\csname pgfutil@ifundefined\endcsname{mylistmacro}{\def\mylistmacro{#1}}{% Instantiate list if not already
\expandafter\def\expandafter\mylistmacro\expandafter{\mylistmacro^^J#1}}% Append to list
}%
我实际上想做的是:
(使用pgf
)
\def\appendtolist#1#2{% <macro representing list> <item>
\csname pgfutil@ifundefined\endcsname{#1}{\def\ithapplist{#1}}{% Instantiate list if not already
\expandafter\def\expandafter#1\expandafter{\ithapplist^^J#1}}% Append to list
}%
问题
之后\endcsname
我需要提供一个不带反斜杠的宏名。
即使我使用其他语法来确定宏是否已定义,我仍然会遇到这个问题。
其他 csname 检查
TeX 内核
https://tex.stackexchange.com/a/30484/13552
\ifcsname#1\endcsname%
... command '#1' exists ...%
\else%
... command '#1' does not exist ...%
\fi%
LateX 内核
https://tex.stackexchange.com/a/30486/13552强调文字
\@ifundefined{foo}
{%
% \foo not defined
}
{%
% \foo defined
}%
最终目标
通常,我会在运行时使用 将内容吐出到日志中\typeout
。相反,我想将它们附加到宏(分隔变量)中,以便稍后使用类似 的内容调用\typeout\expandafter{\aggregatedlogentries}
。这会使某些内容在日志中分组。
例子
无法编译
\documentclass{article}
\usepackage{pgf}
\def\appendtolist#1{% <item>
\csname pgfutil@ifundefined\endcsname{mylistmacro}{\def\mylistmacro{#1}}{% Instantiate list if not already
\expandafter\def\expandafter\mylistmacro\expandafter{\mylistmacro^^J#1}}% Append to list
}%
\begin{document}
\newcount\step
\step = 0%
\loop
\appendtolist{\step}% <== I want to be able to provide a macro name as arg1 and item as arg2!
\advance\step by 1%
\unless\ifnum \step>10 %space important
\repeat %
\typeout{\mylistmacro}
\end{document}
答案1
这是程序员使用复杂的宏包(如)解决不存在的问题的明显例子pgf
。您可以简单地执行以下操作:
\def\appendtolist#1#2{%
\ifx#1\undefined \def#1{#2}\else
\expandafter\def\expandafter#1\expandafter{#1^^J#2}\fi % Append to list
}%
\appendtolist\ithaplist{aha} \appendtolist\ithaplist{uha}
答案2
您的代码没有产生错误,而只是简单地定义\mylistmacro
为 10 ,\step
因为您确实将标记附加了\step^^J
10 次,在这里我附加了当前值的扩展\step
,尽管正如 wipet 正确指出的那样,这使用的代码比所述用例所需的代码多几个数量级。
\documentclass{article}
%no \usepackage{etex}% for \unless
\usepackage{pgf}
\makeatletter
\def\appendtolist#1{% <item>
\pgfutil@ifundefined{mylistmacro}{\def\mylistmacro{#1}}{% Instantiate list if not already
\expandafter\def\expandafter\mylistmacro\expandafter{\mylistmacro^^J#1}}% Append to list
}%
\begin{document}
\newcount\step
\step = 0%
\loop
\expandafter\appendtolist\expandafter{\the\step}% <== I want to be able to provide a macro name as arg1 and item as arg2!
\advance\step by 1%
\unless\ifnum \step>10 %space important
\repeat %
\typeout{\mylistmacro}
\end{document}
答案3
答案4
和etoolbox
:
\usepackage{etoolbox}
\newcommand{\appendtolist}[2]{%
\ifundef{#1}{\gdef#1{== \string#1 ==}}{}%
\gappto#1{^^J#2}%
}
\appendtolist\mylistmacro{abc}
\appendtolist\mylistmacro{def}
\appendtolist\mylistmacro{ghi}
\appendtolist\mylistmacro{lmn}
\typeout{\mylistmacro}
终端输出:
== \mylistmacro ==
abc
def
ghi
lmn
更加可定制,因为您可以定义所制作列表的任何用途,只需改变定义方式即可\showlist
。
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\appendtolist}{mm}
{
\seq_if_exist:cF { g_macmadness_typeout_#1_seq }
{ \seq_new:c { g_macmadness_typeout_#1_seq } }
\seq_gput_right:cn { g_macmadness_typeout_#1_seq } { #2 }
}
\NewDocumentCommand{\showlist}{m}
{
\typeout
{
==~#1~==^^J
\seq_use:cn { g_macmadness_typeout_#1_seq } { ^^J }
}
}
\ExplSyntaxOff
\appendtolist{mylistmacro}{abc}
\appendtolist{mylistmacro}{def}
\appendtolist{mylistmacro}{ghi}
\appendtolist{mylistmacro}{lmn}
\showlist{mylistmacro}
终端输出
== mylistmacro ==
abc
def
ghi
lmn