如何定义一个具有完全展开宏的值的宏?

如何定义一个具有完全展开宏的值的宏?

有关的

我为列表制作了一些简单的宏,但我不知道如何使用 保存值\edef

我对创建列表的其他方式不感兴趣,因为这只是一个实验。

我想知道如何保存完全扩展的宏的值。

例如:\unhbox\edef

编辑:我知道它不起作用,只是举了一个例子来解释它在 内部扩展\hbox但不在 内部扩展的想法\edef

例子:

\newlist\mylist
\mylist{append}{hello world}
\begin{document}
    \setbox0=\hbox{\mylist[0]}
    \mylist[0]={bye}
    \edef\value{\unhbox0}
    Saved value: \value\par
    Meaning: {\tt\meaning\value}\par
    Current value: \mylist[0]
\end{document}

unhbox 示例

我正在考虑制作一个可以扩展或表现得像\unhbox

列表的代码

\makeatletter
\def\@parcialexpand#1#2{%
    \def\reserved@a{#1}%
    \edef\reserved@b{#2}%
    \expandafter\reserved@a\reserved@b%
}

\def\@argument#1#2{%
    \begingroup%
        \def\reserved@a{\global#1=}%
        \begingroup%
            \aftergroup\reserved@a\aftergroup{%
                \aftergroup##%
                \aftergroup#2%
            \aftergroup}%
        \endgroup%
    \endgroup%
}

\def\@list@command#1#2{\csname @list@name@#1@command@#2\endcsname}

\def\@list@value#1#2{\csname @list@name@#1@value@#2\endcsname}

\long\def\@list@setvalue#1#2#3{%
    \begingroup%
        \@temptokena=\expandafter{\@list@value{#1}{#2}}%
        \def\reserved@a##1{\@temptokena=\expandafter{##1}}%
        \expandafter\reserved@a\expandafter{\the\@temptokena}%
%
        \edef\reserved@a{\the\@temptokena}%
        \expandafter\gdef\reserved@a{#3}%
    \endgroup%
}

\def\@list@ifexists#1{%
    \edef\reserved@a{\csname @list@name@#1@exists\endcsname}%
    \@temptokena=\expandafter{\csname @list@name@#1@exists\endcsname}%
    \edef\reserved@b{\the\@temptokena}%
    \ifx\reserved@b\reserved@a\relax%
}

\long\def\@list@append#1#2{%
    \begingroup%
        \@tempcnta=\@list@command{#1}{len}%
        %
        \def\reserved@a##1{%
            \@list@setvalue{#1}{##1}{#2}%
        }%
        \expandafter\reserved@a\the\@tempcnta%
%
        \@temptokena=\expandafter{\@list@command{#1}{len}}%
        \def\reserved@a##1{\@temptokena=\expandafter{##1}}%
        \expandafter\reserved@a\expandafter{\the\@temptokena}%
        \edef\reserved@a{\the\@temptokena}%
        %
        \advance\@tempcnta by 1%
        \expandafter\xdef\reserved@a{\the\@tempcnta}%
    \endgroup%
}

\def\@list@pop#1{%
    \begingroup%
        \@tempcnta=\@list@command{#1}{len}%
        %
        \@temptokena=\expandafter{\@list@command{#1}{len}}%
        \def\reserved@a##1{\@temptokena=\expandafter{##1}}%
        \expandafter\reserved@a\expandafter{\the\@temptokena}%
        \edef\reserved@a{\the\@temptokena}%
        %
        \advance\@tempcnta by -1%
        \expandafter\xdef\reserved@a{\the\@tempcnta}%
%
        \def\reserved@a##1{%
            \@list@value{#1}{##1}%
        }%
        \expandafter\reserved@a\the\@tempcnta%
    \endgroup%
}

\def\@list@push#1#2{%
    \begingroup%
        \def\reserved@a##1{\@list{#1}{append}{##1}}%
        \expandafter\reserved@a\expandafter{#2}%
    \endgroup%
}

\def\@list@checkexists#1{%
    \@list@ifexists{#1}%
        \@latex@error{\string\@list: Undefined list: #1}{}%
    \fi%
}
\def\@list@checknoexists#1{%
    \@list@ifexists{#1}%
        \relax%
    \else%
        \@latex@error{\string\@list: Already exists: #1}{}%
    \fi%    
}

\def\@list#1{%
    \@list@checkexists{#1}%
    \@ifnextchar[{%
        \@argument\@temptokena{1}%
        \@parcialexpand{\def\reserved@a}{[\the\@temptokena]}{%
            \@ifnextchar={%
                \@argument\@temptokena{1}%
                \@parcialexpand{\def\reserved@a=}{\the\@temptokena}{%
                    \@list@setvalue{#1}{####1}{################1}%
                }%
                \reserved@a%
            }{%s
                \@list@value{#1}{####1}%
            }%
        }%
        \reserved@a%
    }{%
        \@argument\@temptokena{1}%
        \@parcialexpand{\def\reserved@a}{\the\@temptokena}{%
            \@list@command{#1}{####1}%
        }%
        \reserved@a%
    }%
}

\def\@list@newlist#1#2{%
    \@list@checknoexists{#1}%
    \expandafter\def\csname @list@name@#1@exists\endcsname{}%
    \expandafter\def\csname @list@name@#1@command@len\endcsname{0}%
    \expandafter\def\csname @list@name@#1@command@append\endcsname{\@list@append{#1}}%
    \expandafter\def\csname @list@name@#1@command@pop\endcsname{\@list@pop{#1}}%
    \expandafter\def\csname @list@name@#1@command@push\endcsname{\@list@push{#1}}%
    \def#2{\@list{#1}}%
}
\def\newlist#1{\expandafter\@list@newlist\expandafter{\string#1}#1}
\makeatother

笔记: push扩展值并执行append

一个例子

\newlist\list
\list{append}{hello world}

\begin{document}
        Len is \list{len}\par
        [0]: \list[0]
\end{document}

出去

当我尝试使用\edef

\begin{document}
        Len is \list{len}\par
        [0]: \list[0]

        \edef\zerovalue{\list[0]}
\end{document}

! TeX capacity exceeded, sorry [input stack size=5000].
\@argument #1#2->\begingroup \def \reserved@a 
                                              {\global #1=}\begingroup \afte...
l.149   \edef\zerovalue{\list
                            [0]}
!  ==> Fatal error occurred, no output PDF file produced!

简单追踪

\def\expand#1{%
    \toks0=\expandafter{#1}%
    \showthe\toks0%
}
\def\makeexpand#1{\expandafter\expand\expandafter{#1}}
\makeexpand{\list[0]}
\makeexpand{\the\toks0}
\makeexpand{\the\toks0}
\message{LOOP^^J}
\makeexpand{\the\toks0}

> \@list@checkexists {\list}\@ifnextchar [{\@argument \@temptokena {1}\@parcial
expand {\def \reserved@a }{[\the \@temptokena ]}{\@ifnextchar ={\@argument \@te
mptokena {1}\@parcialexpand {\def \reserved@a =}{\the \@temptokena }{\@list@set
value {\list}{####1}{################1}}\reserved@a }{\@list@value {\list}{####
1}}}\reserved@a }{\@argument \@temptokena {1}\@parcialexpand {\def \reserved@a 
}{\the \@temptokena }{\@list@command {\list}{####1}}\reserved@a }[0].
l.151 \makeexpand{\list[0]}

> \@list@ifexists {\list}\@latex@error {\string \@list : Undefined list: \list}
{}\fi \@ifnextchar [{\@argument \@temptokena {1}\@parcialexpand {\def \reserved
@a }{[\the \@temptokena ]}{\@ifnextchar ={\@argument \@temptokena {1}\@parciale
xpand {\def \reserved@a =}{\the \@temptokena }{\@list@setvalue {\list}{####1}{#
###############1}}\reserved@a }{\@list@value {\list}{####1}}}\reserved@a }{\@ar
gument \@temptokena {1}\@parcialexpand {\def \reserved@a }{\the \@temptokena }{
\@list@command {\list}{####1}}\reserved@a }[0].
l.152 \makeexpand{\the\toks0}

> \edef \reserved@a {\csname @list@name@\list@exists\endcsname }\@temptokena =\
expandafter {\csname @list@name@\list@exists\endcsname }\edef \reserved@b {\the
 \@temptokena }\ifx \reserved@b \reserved@a \relax \@latex@error {\string \@lis
t : Undefined list: \list}{}\fi \@ifnextchar [{\@argument \@temptokena {1}\@par
cialexpand {\def \reserved@a }{[\the \@temptokena ]}{\@ifnextchar ={\@argument 
\@temptokena {1}\@parcialexpand {\def \reserved@a =}{\the \@temptokena }{\@list
@setvalue {\list}{####1}{################1}}\reserved@a }{\@list@value {\list}{
####1}}}\reserved@a }{\@argument \@temptokena {1}\@parcialexpand {\def \reserve
d@a }{\the \@temptokena }{\@list@command {\list}{####1}}\reserved@a }[0].
l.153 \makeexpand{\the\toks0}

LOOP
> \edef \reserved@a {\csname @list@name@\list@exists\endcsname }\@temptokena =\
expandafter {\csname @list@name@\list@exists\endcsname }\edef \reserved@b {\the
 \@temptokena }\ifx \reserved@b \reserved@a \relax \@latex@error {\string \@lis
t : Undefined list: \list}{}\fi \@ifnextchar [{\@argument \@temptokena {1}\@par
cialexpand {\def \reserved@a }{[\the \@temptokena ]}{\@ifnextchar ={\@argument 
\@temptokena {1}\@parcialexpand {\def \reserved@a =}{\the \@temptokena }{\@list
@setvalue {\list}{####1}{################1}}\reserved@a }{\@list@value {\list}{
####1}}}\reserved@a }{\@argument \@temptokena {1}\@parcialexpand {\def \reserve
d@a }{\the \@temptokena }{\@list@command {\list}{####1}}\reserved@a }[0].
l.155 \makeexpand{\the\toks0}

答案1

您的\list[0]扩展性不是完全可扩展的。\unhbox不过,您所说的“扩展”是什么意思还不清楚。

这是一个不同的实现:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\newlist}{m}
 {
  % allocate the new list
  \montecino_lists_newlist:Nf #1 { \cs_to_str:N #1 }
 }

\cs_new_protected:Nn \montecino_lists_newlist:Nn
 {
  \seq_new:c { l_montecino_lists_#2_seq }
  \NewExpandableDocumentCommand{#1}{m}
   {
    \str_case:nnF { ##1 }
     {
      {len}{ \montecino_lists_len:n { #2 } }
      {append}{ \montecino_lists_append:nn { #2 } }
      {push}{ \montecino_lists_append:nn { #2 } }
      {pop}{ \montecino_lists_pop:n { #2 } }
     }
     { \montecino_lists_get:nn { #2 } { ##1 + 1 } }
   }
 }
\cs_generate_variant:Nn \montecino_lists_newlist:Nn { Nf }

\cs_new:Nn \montecino_lists_len:n
 {
  \seq_count:c { l_montecino_lists_#1_seq }
 }
\cs_new_protected:Nn \montecino_lists_append:nn
 {
  \seq_put_right:cn { l_montecino_lists_#1_seq } { #2 }
 }
\cs_new_protected:Nn \montecino_lists_pop:n
 {
  \seq_pop_right:cN { l_montecino_lists_#1_seq } \l_tmpa_tl
  \tl_use:N \l_tmpa_tl
 }
\cs_new:Nn \montecino_lists_get:nn
 {
  \seq_item:cn { l_montecino_lists_#1_seq } { #2 }
 }

\ExplSyntaxOff

\newlist\mylist

\mylist{append}{hello world}

\begin{document}

Len is \mylist{len}

[0]: \mylist{0}

\mylist{append}{ABC} \mylist{len}

\mylist{push}{DEF} \mylist{len}

\mylist{0} \mylist{1} \mylist{2}

\mylist{pop} \mylist{len}

\edef\test{\mylist{len}}\texttt{\meaning\test}

\edef\test{\mylist{0}}\texttt{\meaning\test}

\end{document}

append我看不出你的和之间的区别push,所以我用相同的功能实现了它们。

我也更改了名称,因为\list它是在 LaTeX 中使用的。

在此处输入图片描述

相关内容