可扩展的‘字符扫描’命令?

可扩展的‘字符扫描’命令?

请考虑以下 MWE,对于“字符扫描”命令“ \looper”,它利用\@tfor

\documentclass{minimal}

\usepackage{trace}

\makeatletter
\newcommand\looper[1]{%
% \def\looper#1{%
\typeout{#1}%
\@tfor\next:=#1 \do{\typeout{\next}%
\next%
}
}
\makeatother

\begin{document}

\looper{TEST1}
%% terminal typeout:
% TEST1
% T
% E
% S
% T
% 1


%\typeout{\looper{Test2}}
%% terminal typeout:
% ! Undefined control sequence.
% \next ->\@nil

\edef\tmptest{TEST3}
\looper{\tmptest}
%% terminal typeout:
% TEST3
% TEST3

% \traceon
\edef\outtest{\looper{\tmptest}}
%% terminal typeout:
% ! Undefined control sequence.
% \next ->\@nil

\end{document}

这里的\looper{TEST1}行为正如我想要的那样,但我还想以某种方式使用\looper{\tmptest}(其中\edef\tmptest{TEST3})并获取(在终端中):

\looper{\tmptest}
%% terminal typeout:
% TEST3
% T
% E
% S
% T
% 3

但是,函数实际上不必自行扩展参数,只要我可以在调用本身中执行某些操作即可,例如\looper{\detokenize{\tmptest}}否则我不能在这里使用它,因为它不会“解压”字符

此外,该函数会“返回”\next每个扫描到的字符,因此我希望能够编写类似

\edef\outtest{\looper{\tmptest}}

...并再次获得“TEST3”的内容- 除了这里,它们将是路由\outtest连接的结果(\next\looper因此,我可以改为返回-\next\next并使用如下函数获取“-TEST-3”)。

是否已经内置了类似的东西 - 或者有人可以指出包含类似功能的资源?


编辑:请注意,可能这个没有扩展,因为\@tfor使用不可扩展的(?)命令(\@nil) - 如果我激活,我会得到这个\traceon

% with \traceon:
{into \tracingonline=1}
{\edef}

\looper #1->\typeout {#1}\@tfor \next :=#1 \do {\typeout {\next }\next }
#1<-\tmptest

\typeout #1->\begingroup \set@display@protect \immediate \write \@unused {#1}\e
ndgroup
#1<-\tmptest

\set@display@protect ->\let \protect \string
{\string}

\tmptest ->TEST3

\@tfor #1:=->\@tf@r #1
#1<-\next

\@tf@r #1#2\do #3->\def \@fortmp {#2}\ifx \@fortmp \space \else \@tforloop #2\@
nil \@nil \@@ #1{#3}\fi
#1<-\next
#2<- \tmptest
#3<-\typeout {\next }\next

\@fortmp -> \tmptest

\tmptest ->TEST3

\tmptest ->TEST3
{\ifx}
{false}

\@tforloop #1#2\@@ #3#4->\def #3{#1}\ifx #3\@nnil \expandafter \@fornoop \else
#4\relax \expandafter \@tforloop \fi #2\@@ #3{#4}
#1<-\tmptest
#2<- \@nil \@nil
#3<-\next
#4<-\typeout {\next }\next

\next ->\@nil
{undefined}
! Undefined control sequence.
\next ->\@nil

答案1

正如评论中所述,您无法进行可扩展的分配,但这里有一个可扩展循环的可能定义,它只围绕[]每个标记:

\def\expandloop#1{\xloop#1\relax}
\def\xloop#1{%
  \ifx\relax#1\else[#1]\expandafter\xloop\fi}

\edef\zzzz{\expandloop{TEST1}}

\show\zzzz

\bye

运行结果如下:

$ tex loop
This is TeX, Version 3.1415926 (TeX Live 2011/Cygwin)
(./loop.tex
> \zzzz=macro:
->[T][E][S][T][1].
l.8 \show\zzzz

答案2

在 LaTeX3 中,我们有一个名为 的循环\tl_map_function:nN,它似乎可以满足您的要求。当然,它可以用原语重新编码,为了方便参考,我在这里这样做了:

\documentclass{article}

\usepackage{pdftexcmds}


\makeatletter
\long\def\expandableloop#1#2{%
  \expandableloop@aux#1#2\q@recursion@tail
  \break@point
}
\long\def\expandableloop@aux#1#2{%
  \break@if@quark@tail{#2}%
  #1{#2}%
  \expandableloop@aux#1%
}
\long\def\break@if@quark@tail#1{%
  \ifnum\pdf@strcmp{\noexpand\q@recursion@tail}{\unexpanded{#1}}=\z@
    \expandafter\break@if@quark@tail@aux
  \fi
}
\long\def\break@if@quark@tail@aux#1\break@point{}

\makeatletter
\newcommand\looper[1]{%
 \expandableloop\detokenize{#1}
}
\makeatother

\begin{document}

\def\tmptest{TEST3}
\edef\outtest{\expandafter\looper\expandafter{\tmptest}}
\show\outtest

\end{document}

请注意,这依赖于\pdfstctmp或等效功能:我已加载包pdftexcmds来整理此处的引擎可变性。还请注意,这不会“意外地”扩展输入,因此我不得不故意使用 来这样做\expandafter

相关内容