それを反復するためのモジュラーマクロリスト構造

それを反復するためのモジュラーマクロリスト構造

に基づくワイペットの答え、そして同じ学習精神で、反復ループ「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

(マクロはLaTeX 2e の -environment\listで既に定義され、使用されています。 したがって、以下の例では、代わりにマクロが定義され、使用されています。)list
\MyList

たとえば、リストを保持するマクロを展開し、その後引数を交換するという問題に簡単に変えることができます。

以下の例では、 -construct の後ろのトークン ストリームによって形成される配置内でリスト (中括弧でネストされている) を移動することによって\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リストをどうすれば数を知ることができますか?\expandaftercsname マクロに追加するときに 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>

2番目の必須引数は、テンプレートで設定された引数を使用するコードです。省略形single(何も指定されていない場合はデフォルト)がありdoubletriple

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

それぞれ。

ここに画像の説明を入力してください

関連情報