模組化巨集列表結構來迭代它

模組化巨集列表結構來迭代它

基於維佩特的回答,並且以同樣的學習精神,關於迭代循環“for”,找出所提出的“for循環”如何更加模組化是很有趣的。我想傳遞上面範例中的可迭代列表作為參數。

\documentclass[a4paper]{article}
\usepackage{pst-solides3d}

%%% FOR LOOP %%%
\makeatletter
\long\def\for#1in#2#3{\expandafter\def\csname b:\string#1\endcsname{#3}%
   \@forinA#1#2;}
\long\def\@forinA#1#2;{\ifx#2\else
   \def#1{#2}\csname b:\string#1\endcsname \expandafter\@forinA\expandafter#1\fi}
%%%%%%%%%%%%%%%%%%
\makeatother

%% Variables%%
\pgfmathparse{1.2}\edef\linkLength{\pgfmathresult}
\pgfmathparse{0.2}\edef\jointRadio{\pgfmathresult}
\pgfmathparse{0.6}\edef\jointLength{\pgfmathresult}

\newcommand{\iterating}{
%%% point's structure  %%%
\for\i in {%
0 0 0;% N°0
0 0 0;% N°1 
0 0 \linkLength;% N°2 
0 0 \jointLength;% N°3
0 {\jointLength*0.5} {\linkLength + \jointRadio};% N°4
}
{%  
  \i\par
   %... call to several macros
}%
}
\begin{document}

\iterating

\end{document}

程式碼行為對於我的目的來說是正確的。

0 0 0
0 0 0
0 0 1.2
0 0 0.6
0 0.6*0.5 1.2+ 0.2

這個列表是一個隱式列表,每個元件都有幾個變數和算術運算。因此,主要思想是將列表作為巨集傳遞,例如\newcommand{\list}{0 0 0;0 0 0;0 0 \linkLength;0 0 \jointLength;0 {\jointLength*0.5} {\linkLength + \jointRadio}}並將其稱為\for\i in \list.我不明白聲明中需要進行哪些修改才能達到此行為。 (我意識到可以使用 \foreach 語句來實現此行為,但我需要了解如何完成)

任何想法,都會受到好評。

答案1

(該巨集\list已定義並用於listLaTeX 2e 中的 -environment。
因此,在下面的範例中,\MyList定義並使用了該巨集。)

例如,您可以輕鬆地將問題變成擴展保存清單的巨集然後交換參數的問題。

在下面的範例中,\expandafter用於按\MyList時間順序擴展巨集(其擴展產生要迭代的列表),然後透過\PassFirstToSecond在 - 構造後面的令牌流形成的排列中移動該列表(嵌套在大括號中)\for\i in

\documentclass[a4paper]{article}
\usepackage{pst-solides3d}

%%% FOR LOOP %%%
\makeatletter
\long\def\for#1in#2#3{\expandafter\def\csname b:\string#1\endcsname{#3}%
   \@forinA#1#2;}
\long\def\@forinA#1#2;{\ifx#2\else
   \def#1{#2}\csname b:\string#1\endcsname \expandafter\@forinA\expandafter#1\fi}
%%%%%%%%%%%%%%%%%%
\makeatother

%% Variables%%
\pgfmathparse{1.2}\edef\linkLength{\pgfmathresult}
\pgfmathparse{0.2}\edef\jointRadio{\pgfmathresult}
\pgfmathparse{0.6}\edef\jointLength{\pgfmathresult}

\newcommand{\iterating}{%%%%%%%%%%%%%
%%% point's structure  %%%
\for\i in {%
0 0 0;% N°0
0 0 0;% N°1 
0 0 \linkLength;% N°2 
0 0 \jointLength;% N°3
0 {\jointLength*0.5} {\linkLength + \jointRadio};% N°4
}
{%  
  \i\par
   %... call to several macros
}%
}


\newcommand\PassFirstToSecond[2]{#2{#1}}

\newcommand\MyList{%
  0 0 0;% N°0
  0 0 0;% N°1 
  0 0 \linkLength;% N°2 
  0 0 \jointLength;% N°3
  0 {\jointLength*0.5} {\linkLength + \jointRadio};% N°4
}%



\begin{document}

\noindent\verb|\iterating| yields:

\iterating

\bigskip

\noindent\verb|\expandafter\PassFirstToSecond\expandafter{\MyList}{\for\i in }{\i\par}| yields:

\expandafter\PassFirstToSecond\expandafter{\MyList}{\for\i in }{\i\par}%

\bigskip

\noindent You can also do another kind of \verb|\expandafter|-orgy:

\bigskip

\noindent\verb|\expandafter\for\expandafter\i\expandafter i\expandafter n\expandafter{\MyList}{\i\par}| yields:

\expandafter\for\expandafter\i\expandafter i\expandafter n\expandafter{\MyList}{\i\par}%

\end{document}

在此輸入影像描述


您也可以使用巨集\romannumeral\Expandtimes來指定保存清單的參數所需的擴充等級 -\romannumeral\Expandtimes中進行了解釋\expandafter附加到 csname 巨集時如何知道 s 的數量?

\documentclass[a4paper]{article}
\usepackage{pst-solides3d}

%%% FOR LOOP %%%
\makeatletter
%
\newcommand\exchange[2]{#2#1}%
% A check is needed for finding out if an argument is catcode-11-"d" while there are only 
% the possibilities that the argument is either a single catcode-11-"d"
% or a single catcode-12-"m":
\def\innerdfork#1d#2#3dd{#2}%
\def\dfork#1{\innerdfork#1{\@firstoftwo}d{\@secondoftwo}dd}%
% By means of \romannumeral create as many catcode-12-characters m as expansion-steps are to take place.
% Then by means of recursion for each of these m double the amount of `\expandafter`-tokens and
% add one `\expandafter`-token within \innerExp's first argument.
\def\Expandtimes#1{0\expandafter\innerExp\expandafter{\expandafter}\romannumeral\number\number#1 000d}
\def\innerExp#1#2{\dfork{#2}{#1 }{\innerExp{#1#1\expandafter}}}


\long\def\for#1in #2-level-expansion of #3#4{%
  \expandafter\def\csname b:\string#1\endcsname{#4}%
  \expandafter\exchange\expandafter{\romannumeral\Expandtimes{#2}#3;}{\@forinA#1}%
}
\long\def\@forinA#1#2;{\ifx#2\else
   \def#1{#2}\csname b:\string#1\endcsname \expandafter\@forinA\expandafter#1\fi}
%%%%%%%%%%%%%%%%%%
\makeatother

%% Variables%%
\pgfmathparse{1.2}\edef\linkLength{\pgfmathresult}
\pgfmathparse{0.2}\edef\jointRadio{\pgfmathresult}
\pgfmathparse{0.6}\edef\jointLength{\pgfmathresult}

\newcommand\MyList{%
  0 0 0;%
  0 0 0;%
  0 0 \linkLength;%
  0 0 \jointLength;%
  0 {\jointLength*0.5} {\linkLength + \jointRadio};%
}%

\newcommand\MyOuterListContainer{\MyInnerListContainer}
\newcommand\MyInnerListContainer{\MyList}


\begin{document}

\begingroup
\topsep=0ex \partopsep=0ex
\begin{verbatim}
\for\i in 0-level-expansion of {%
  0 0 0;%
  0 0 0;%
  0 0 \linkLength;%
  0 0 \jointLength;%
  0 {\jointLength*0.5} {\linkLength + \jointRadio};%
}{\i\par}%
\end{verbatim}%
\smallskip
\endgroup

\noindent yields:

\for\i in 0-level-expansion of {%
  0 0 0;%
  0 0 0;%
  0 0 \linkLength;%
  0 0 \jointLength;%
  0 {\jointLength*0.5} {\linkLength + \jointRadio};%
}{\i\par}%

\bigskip

\noindent\verb|\for\i in 1-level-expansion of {\MyList}{\i\par}| yields:

\for\i in 1-level-expansion of {\MyList}{\i\par}

\bigskip

\noindent\verb|\for\i in 3-level-expansion of {\MyOuterListContainer}{\i\par}| yields:

\for\i in 3-level-expansion of {\MyOuterListContainer}{\i\par}

\end{document}

在此輸入影像描述

答案2

\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{pst-solides3d}
%% Variables%%
\pgfmathparse{1.2}\edef\linkLength{\pgfmathresult}
\pgfmathparse{0.2}\edef\jointRadio{\pgfmathresult}
\pgfmathparse{0.6}\edef\jointLength{\pgfmathresult}
\newcommand\itlist{
0 0 0;% N°0
0 0 0;% N°1 
0 0 \linkLength;% N°2 
0 0 \jointLength;% N°3
0 {\jointLength*0.5} {\linkLength + \jointRadio};% N°4
}
\usepackage{listofitems}
\begin{document}
\setsepchar{;/ }
\ignoreemptyitems
\readlist*\mylist{\itlist}
Iterate by row:
\foreachitem\x\in\mylist[]{\par%
  \fbox{\x}
}

Third item on 5th row (the actual tokens):\\
\detokenize\expandafter\expandafter\expandafter{\mylist[5,3]}\\
which expands to \mylist[5,3]

1st, 3rd items on 3rd row, in a box is \fbox{\mylist[3,2],\mylist[3,3]}

Now to iterate on each item:
\foreachitem\x\in\mylist{\par%
  \foreachitem\y\in\mylist[\xcnt]{%
    \fbox{\y}
}}
\end{document}

在此輸入影像描述

答案3

這是我為了休閒而開發的一些程式碼。將以下程式碼另存為extforeach-code.tex

% extforeach-code.tex

\ExplSyntaxOn
\providecommand\fpeval{\fp_eval:n}

\NewDocumentCommand{\nforeach}{ m +m }
 {
  \tl_clear:N \l__manual_nforeach_type_tl
  \keys_set:nn { manual/nforeach }
   {
    type=integers,start = 1, step = 1, end = 0,
   }
  \keys_set:nn { manual/nforeach } { #1 }
  \__manual_nforeach_exec:n { #2 }
 }

\int_new:N \g__manual_foreach_map_int
\int_new:N \g__manual_fp_map_int
\tl_new:N \l__manual_nforeach_type_tl

\keys_define:nn { manual/nforeach }
 {
  type .choice:,
  type .value_required:n = true,
  type/integers .code:n = \tl_set:Nn \l__manual_nforeach_type_tl { integers },
  type/fp       .code:n = \tl_set:Nn \l__manual_nforeach_type_tl { fp },
  type/alph     .code:n = \tl_set:Nn \l__manual_nforeach_type_tl { alph },
  type/Alph     .code:n = \tl_set:Nn \l__manual_nforeach_type_tl { Alph },
  start .tl_set:N = \l__manual_nforeach_start_tl,
  step  .tl_set:N = \l__manual_nforeach_step_tl,
  end   .tl_set:N = \l__manual_nforeach_end_tl,
 }

\cs_new_protected:Nn \__manual_nforeach_exec:n
 {
  \int_gincr:N \g__manual_foreach_map_int
  \str_case:Vn \l__manual_nforeach_type_tl
   {
    {integers}{\__manual_nforeach_exec_integers:n { #1 }}
    {fp}      {\__manual_nforeach_exec_fp:n { #1 }}
    {alph}    {\__manual_nforeach_exec_alph:Nn \int_to_alph:n { #1 }}
    {Alph}    {\__manual_nforeach_exec_alph:Nn \int_to_Alph:n { #1 }}
   }
  \int_gdecr:N \g__manual_foreach_map_int
 }
\cs_generate_variant:Nn \str_case:nn { V }

\cs_new_protected:Nn \__manual_nforeach_exec_integers:n
 {
  \int_step_inline:nnnn
   { \l__manual_nforeach_start_tl }
   { \l__manual_nforeach_step_tl }
   { \l__manual_nforeach_end_tl }
   { #1 }
 }
\cs_new_protected:Nn \__manual_nforeach_exec_alph:Nn
 {
  \cs_set:cn { __manual_nforeach_alph_ \int_use:N \g__manual_foreach_map_int :n } { #2 }
  \cs_generate_variant:cn
   { __manual_nforeach_alph_ \int_use:N \g__manual_foreach_map_int :n }
   { f }
  \int_step_inline:nnnn
   { \int_from_alph:f { \l__manual_nforeach_start_tl } }
   { \l__manual_nforeach_step_tl }
   { \int_from_alph:f { \l__manual_nforeach_end_tl } }
   {
    \use:c { __manual_nforeach_alph_ \int_use:N \g__manual_foreach_map_int :f }
     { #1 { ##1 } }
   }
 }
\cs_generate_variant:Nn \cs_generate_variant:Nn { c }
\cs_generate_variant:Nn \int_from_alph:n { f }

\cs_new_protected:Nn \__manual_nforeach_exec_fp:n
 {
  \fp_step_inline:nnnn
   { \l__manual_nforeach_start_tl }
   { \l__manual_nforeach_step_tl }
   { \l__manual_nforeach_end_tl }
   { #1 }
 }

\NewDocumentCommand{\lforeach}{ s O{} m +m }
 {
  \IfBooleanTF{#1}
   {
    \manual_lforeach:non { #2 } { #3 } { #4 }
   }
   {
    \manual_lforeach:nnn { #2 } { #3 } { #4 }
   }
 }

\cs_new_protected:Nn \manual_lforeach:nnn
 {
  \keys_set:nn { manual/lforeach } { single }
  \keys_set:nn { manual/lforeach } { #1 }
  \clist_set:Nn \l__manual_lforeach_list_clist { #2 }
  \int_gincr:N \g__manual_foreach_map_int
  \__manual_lforeach_define:n { #3 }
  \clist_map_inline:Nn \l__manual_lforeach_list_clist
   {
    \use:c { __manual_lforeach_ \int_use:N \g__manual_foreach_map_int _action:w } ##1 \q_stop
   }
  \int_gdecr:N \g__manual_foreach_map_int
 }
\cs_generate_variant:Nn \manual_lforeach:nnn { no }

\cs_new_protected:Nn \__manual_lforeach_define:n
 {
  \exp_last_unbraced:NcV
   \cs_set:Npn
   { __manual_lforeach_ \int_use:N \g__manual_foreach_map_int _action:w }
   \l__manual_lforeach_format_tl
   \q_stop
   {#1}
 }

\keys_define:nn { manual/lforeach }
 {
  format .tl_set:N = \l__manual_lforeach_format_tl,
  single .code:n = \tl_set:Nn \l__manual_lforeach_format_tl { ##1 },
  double .code:n = \tl_set:Nn \l__manual_lforeach_format_tl { ##1/##2 },
  triple .code:n = \tl_set:Nn \l__manual_lforeach_format_tl { ##1/##2/##3 },
 }
\ExplSyntaxOff

現在您的文件可以是

\documentclass{article}
\usepackage{xparse,xfp}

\input{extforeach-code.tex}

\newcommand\linkLength{1.2}
\newcommand\jointRadio{0.2}
\newcommand\jointLength{0.6}

\newcounter{lines}

\begin{document}

\lforeach[format=#1 #2 #3]{
  0 0 0, % N°0
  0 0 0, % N°1
  0 0 \linkLength, % N°2
  0 0 \jointLength, % N°3
  0 {\jointLength*0.5} {\linkLength + \jointRadio}, % N°4
}
{%
 \stepcounter{lines}Line \thelines\ is \fpeval{#1}~\fpeval{#2}~\fpeval{#3}\par 
}

\end{document}

借助 的幫助,xfp我們甚至可以計算表達式。

format為作為第一個強制參數給出的逗號分隔清單中的每個項目設定一個模板,這裡#1 #2 #3意味著該項目將包含以下內容

<subitem><space><subitem><space><subitem>

第二個強制參數是使用模板中設定的參數的程式碼。有縮寫single(如果沒有指定則預設),double代表triple

format=#1
format=#1/#2
format=#1/#2/#3

分別。

在此輸入影像描述

相關內容