見つけたコードを理解しようとした

見つけたコードを理解しようとした

このスレッドで、非常に興味深くて便利なコードを見つけましたが、それがどのように動作するのか全く分かりません。https://tex.stackexchange.com/a/584979/261033

参考までに、問題のコードは次のとおりです。

\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\matr#1{\def\matrL{}\matrA#1\end}
\def\matrA#1{\ifx\end#1\pmatrix{\matrL}\else 
   \ifx,#1\addto\matrL{&}\else
   \ifx;#1\addto\matrL{\cr}\else
   \addto\matrL{#1}\fi\fi
   \expandafter\matrA\fi
}

これを として呼び出すと、pmatrix が生成されます。単純な行列を頻繁に操作し、長いコマンド全体を繰り返し入力するのにうんざりしている場合は、非常に便利な機能だと思います。また、これを amsmath パッケージで動作させるには、を に\matr{a,b;c,d}置き換える必要があると指摘する人もいます。\pmatrix{\matrL}\begin{pmatrix}\matrL\end{pmatrix}

とにかく、私はこのコマンドにさらなる変更を加えたいと思っています。たとえば、行/列の区切りとして異なる記号を使用したり、入力を列ごとに解析したり、すべての行列の括弧タイプに一般化したり (つまり、 のように入力する\matr{[)}{...}と、 に似た特定の囲み括弧のセットを含む行列が生成されます\left[\begin{matrix}...\end{matrix}\right)) しますが、そのいずれもまだどのように行うのかわかりません。

これらのコマンドについて何か学ぼうとしたのですが、すぐに問題にぶつかりました。 などのコマンドはあまりにもわかりにくいため、どこにもドキュメントが存在しないようです。Googleで検索してもや など\addtoのコマンドしか見つかりませんでしたが、私には興味がありません。また、これらのコマンドを一覧表示する包括的なTeXリソースも見つかりませんでした。\addtocontents\g@addto@macrohttps://www.latex-project.orgまたは出典: http://www.texdoc.org/

ですので、どなたかこの件について私を助けていただける方がいらっしゃいましたら、これらのコマンドに関する実際の既存のドキュメントを教えていただければ大変助かります。よろしくお願いします。

答え1

マクロ\addtoは別のマクロにコードを追加します。

があり\def\foo{X}、 であれば\addto\foo{Y}、TeXで十分です

\expandafter\def\expandafter\foo\expandafter{\foo Y}

その結果

\def\foo{XY}

チェーンが機能し終えた後\expandafter。しかし、できないは が使用する重要なコマンドであり、再定義すると災害が発生するリスクがある\addtoため、コードを LaTeX で使用する予定の場合は を使用してください。別の名前を使用してください。\addtobabel

は何\matrをしますか? は を実行し\def\matrL{}、行列本体のコンテナを初期化します。次に、引数を に渡して\matrA再帰を開始します。

マクロは\matrA次のトークンを 1 つずつ読み取ります。

  • 次のトークンが,(セルの終わりを示す)の場合、&が追加されます\matrL
  • 次のトークンが;(行の終わりを示す)の場合、\crが追加されます\matrL
  • 次のトークンが の場合\end、エンドゲームが実行され、つまり\pmatrix{\matrL}が実行され、再帰が停止します。
  • それ以外の場合は、トークンは単に に追加されます\matrL

これを LaTeX に、特に特定のpmatrix環境に適応できますか? はい、簡単にできます。

まず、内部マクロに別の名前を選択します (できれば内部マクロ@内)。

\documentclass{article}
\usepackage{amsmath}

\makeatletter
\newcommand{\matr}[1]{\def\tsskyx@matrL{}\tsskyx@matrA#1\end}

\def\tsskyx@addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}

\def\tsskyx@matrA#1{%
  \ifx\end#1%
    \begin{pmatrix}\tsskyx@matrL\end{pmatrix}%
  \else 
    \ifx,#1%
      \tsskyx@addto\tsskyx@matrL{&}%
    \else
      \ifx;#1%
        \tsskyx@addto\tsskyx@matrL{\\}%
      \else
        \tsskyx@addto\tsskyx@matrL{#1}%
      \fi
    \fi
    \expandafter\tsskyx@matrA
  \fi
}
\makeatother

\begin{document}

\[
\matr{a,b;c,d}
\]

\end{document}

同じコードですが、違いは最小限です。 の代わりにと を\cr追加します。\\\begin{pmatrix}...\end{pmatrix}

を使用した別の実装ではexpl3、オプションの引数で区切り文字を指定します (デフォルトはp、規則bvVBに従って にすることができますamsmath)。

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand{\matr}{O{p}m}
 {
  \tsskyx_matr:nn { #1 } { #2 }
 }

\seq_new:N \l__tsskyx_matr_body_seq

\cs_new_protected:Nn \tsskyx_matr:nn
 {
  % build the matrix
  \begin{#1matrix}
  % split the argument at ;
  \seq_set_split:Nnn \l__tsskyx_matr_body_seq { ; } { #2 }
  % map the items, that are comma separated lists
  \seq_map_function:NN \l__tsskyx_matr_body_seq \__tsskyx_matr_row:N
  \end{#1matrix}
 }

\cs_new_protected:Nn \__tsskyx_matr_row:N
 {
  \clist_use:nn { #1 } { & } \\
 }

\ExplSyntaxOff

\begin{document}

\[
\matr{a,b;c,d}
\qquad
\matr[b]{a,b;c,d}
\]

\end{document}

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

行と列の区切りも変更したい場合は、キー値システムを使用できます。

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand{\matr}{O{}m}
 {
  \group_begin:
  \keys_set:nn { tsskyx/matr } { #1 }
  \tsskyx_matr:n { #2 }
  \group_end:
 }

\seq_new:N \l__tsskyx_matr_body_seq
\seq_new:N \l__tsskyx_matr_row_seq

\keys_define:nn { tsskyx/matr }
 {
  row-sep .tl_set:N  = \l__tsskyx_matr_rowsep_tl,
  col-sep .tl_set:N  = \l__tsskyx_matr_colsep_tl,
  delim   .tl_set:N  = \l__tsskyx_matr_delim_tl,
  row-sep .initial:n = { ; },
  col-sep .initial:n = { , },
  delim   .initial:n = { p },
 }

\cs_new_protected:Nn \tsskyx_matr:n
 {
  % build the matrix
  \begin{\l__tsskyx_matr_delim_tl matrix}
  % split the argument at ;
  \seq_set_split:NVn \l__tsskyx_matr_body_seq \l__tsskyx_matr_rowsep_tl { #1 }
  % map the items, that are comma separated lists
  \seq_map_function:NN \l__tsskyx_matr_body_seq \__tsskyx_matr_row:N
  \end{\l__tsskyx_matr_delim_tl matrix}
 }

\cs_new_protected:Nn \__tsskyx_matr_row:N
 {
  \seq_set_split:NVn \l__tsskyx_matr_row_seq \l__tsskyx_matr_colsep_tl { #1 }
  \seq_use:Nn \l__tsskyx_matr_row_seq { & } \\
 }

\ExplSyntaxOff

\begin{document}

\begin{gather*}
\matr{a,b;c,d}
\\
\matr[delim=b]{a,b;c,d}
\\
\matr[row-sep=\\,col-sep=&,delim=V]{a & b \\ c & d}
\\
\matr[row-sep=;,col-sep=:]{a:b;c:d}
\end{gather*}

\end{document}

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

答え2

\addtoコードで言及されているマクロは、もともと csplain 用に設計された OPmac マクロからのもので、後にプレーン TeX 用の OPmac となり、現在は OpTeX で使用されています。これらのマクロ パッケージの作者は LaTeX をサポートしていません。彼のマクロは主にプレーン TeX 用であり、大部分が TeX プリミティブに基づいているため、LaTeX でも適用できます。ただし、LaTeX パッケージ内の同じ名前と共有される名前など、多少の障害が発生することがあります。\addto作者は LaTeX またはそのパッケージ (babel など) を使用していないため、彼にとっても他のプレーン TeX ユーザーにとっても問題はありません。

マクロを変更して、パラメータに行列の括弧タイプを設定できるようにしたい場合は、指定\matrAされたタイプを定義に送信できます。内部マクロ\matr。つまり、次のトリック\defがあります\def:

\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\matr#1#2#3{\def\matrL{}%
   \def\matrA##1{\ifx\end##1\left#1\matrix{\matrL}\right#2\else 
      \ifx,##1\addto\matrL{&}\else
      \ifx;##1\addto\matrL{\cr}\else
      \addto\matrL{##1}\fi\fi
      \expandafter\matrA\fi
   }
   \matrA#3\end
}

Test and usage:
$$
  \matr[]{a,b;c,d}
$$

\bye

編集ここでの別の回答と比較するために、OpTeX のキー値マクロを使用する方法を示します。

\def\matrdefaults{%
   delims=(),   % delimiters of the matrix
   row-sep={;}, % row separator used in parameter
   col-sep={,}, % column separator used in parameter
}
\optdef\matr [] #1{{%
   \readkv\matrdefaults \readkv{\the\opt}%
   \ea\matrX \expanded{\kv{delims}\kv{row-sep}\kv{col-sep}}#1\end
}}
\def\matrX#1#2#3#4{\def\matrL{}%
   \def\matrA##1{\ifx\end##1\left#1\matrix{\matrL}\right#2\else 
      \ifx#4##1\addto\matrL{&}\else
      \ifx#3##1\addto\matrL{\cr}\else
      \addto\matrL{##1}\fi\fi
      \ea\matrA\fi
   }
   \matrA
}

$$
  \displaylines{
     \matr {a,b;c,d} \cr
     \matr [delims={[]}] {a,b;c,d} \cr
     \matr [row-sep={\cr}, col-sep={&}, delims={\|\|}] {a&b\cr c&d} \cr
     \matr [row-sep=;,col-sep=:]{a:b;c:d}
}
$$

\bye

また、このマクロを使用してパッケージを作成する場合は、別の名前空間 (tsskyxここでは ) を使用する必要があります。この名前空間の制御シーケンスには がプレフィックスとして付けられ.、その他の使用される制御シーケンス (プリミティブと OpTeX マクロ) には がプレフィックスとして付けられます_。これにより、マクロはユーザーの名前空間 (プレフィックスのない名前) および異なる名前空間を持つ他のマクロ パッケージから分離されます。

\_namespace{tsskyx}
\_def\.matrdefaults{%
   delims=(),   % delimiters of the matrix
   row-sep={;}, % row separator used in parameter
   col-sep={,}, % column separator used in parameter
}
\_optdef\.matr [] #1{{%
   \_kvdict{tsskyx}%
   \_readkv\.matrdefaults \_readkv{\_the\_opt}%
   \_ea\.matrX \_expanded{\_kv{delims}\_kv{row-sep}\_kv{col-sep}}#1\_end
}}
\_def\.matrX#1#2#3#4{\_def\.matrL{}%
   \_def\.matrA##1{\_ifx\_end##1\_left#1\_matrix{\.matrL}\_right#2\_else 
      \_ifx#4##1\_addto\.matrL{&}\_else
      \_ifx#3##1\_addto\.matrL{\_cr}\_else
      \_addto\.matrL{##1}\_fi\_fi
      \_ea\.matrA\_fi
   }
   \.matrA
}
\_nspublic \matr ;
\_endnamespace

$$
  \displaylines{
     \matr {a,b;c,d} \cr
     \matr [delims={[]}] {a,b;c,d} \cr
     \matr [row-sep={\cr}, col-sep={&}, delims={\|\|}] {a&b\cr c&d} \cr
     \matr [row-sep=;,col-sep=:]{a:b;c:d}
}
$$

\bye

関連情報