modulare Makrolistenstruktur zur Iteration

modulare Makrolistenstruktur zur Iteration

Basierend aufWipets Antwort, und mit dem gleichen Lerngeist über die Iterationsschleife „for“, ist es interessant herauszufinden, wie die vorgeschlagene „for-Schleife“ modularer sein könnte. Ich möchte als Argument die im obigen Beispiel vorgesehene iterierbare Liste übergeben.

\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}

Das Codeverhalten ist für meinen Zweck korrekt.

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

Diese Liste ist eine implizite Liste mit mehreren Variablen und Rechenoperationen in jeder Komponente. Die Hauptidee besteht also darin, die Liste als Makro zu übergeben, etwa so, \newcommand{\list}{0 0 0;0 0 0;0 0 \linkLength;0 0 \jointLength;0 {\jointLength*0.5} {\linkLength + \jointRadio}}und sie als aufzurufen \for\i in \list. Ich verstehe nicht, welche Änderungen in der Deklaration erforderlich sind, um dieses Verhalten zu erreichen. (Mir ist klar, dass dieses Verhalten mit der \foreach-Anweisung erreicht werden könnte, aber ich muss verstehen, wie das geht.)

Alle Ideen werden gerne entgegengenommen.

Antwort1

(Das Makro ist bereits für die -Umgebung in LaTeX 2e \listdefiniert und wird verwendet . Daher wird im folgenden Beispiel stattdessen das Makro definiert und verwendet.)list
\MyList

Sie können die Angelegenheit beispielsweise ganz einfach so umgestalten, dass Sie nur das Makro erweitern, das die Liste enthält, und anschließend die Argumente austauschen.

Im folgenden Beispiel \expandafterwird dazu verwendet, das Makro \MyList(dessen Erweiterung die zu iterierende Liste ergibt) chronologisch zu erweitern, bevor \PassFirstToSeconddiese (in Klammern geschachtelte) Liste innerhalb der Anordnung, die durch den Token-Stream hinter der \for\i in-Konstruktion gebildet wird, verschoben wird.

\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}

Bildbeschreibung hier eingeben


Sie können auch ein Makro wie verwenden, \romannumeral\Expandtimesum die erforderliche Erweiterungsebene mit dem Argument anzugeben, das die Liste enthält:\romannumeral\Expandtimes wird erklärt inWie erfahre ich die Anzahl der\expandafter s beim Anhängen an ein csname-Makro ermitteln?:

\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}

Bildbeschreibung hier eingeben

Antwort2

\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}

Bildbeschreibung hier eingeben

Antwort3

Hier ist ein Code, den ich in meiner Freizeit entwickle. Speichern Sie den folgenden Code alsextforeach-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

Jetzt kann Ihr Dokument

\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}

Mit Hilfe von xfpkönnen wir sogar Ausdrücke auswerten.

Der formatSchlüssel richtet eine Vorlage für jedes Element in der durch Kommas getrennten Liste ein, die als erstes obligatorisches Argument angegeben ist. Hier #1 #2 #3bedeutet dies, dass das Element aus Dingen wie

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

Das zweite obligatorische Argument ist Code, der die in der Vorlage festgelegten Argumente verwendet. Es gibt Abkürzungen single(Standard, wenn nichts angegeben ist), doubledie triplefür

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

jeweils.

Bildbeschreibung hier eingeben

verwandte Informationen