関数の展開を文字列に対してチェックする

関数の展開を文字列に対してチェックする

\Foo与えられた引数に対してどのように展開されるかをテストする関数があります。問題が 2 つあります。1/ の完全に展開されたバージョンを「ログ」に記録できません\Foo{arg}。2/ PDF 出力を見ると展開が正しいように見えても、 に基づくテストは\str_if_eq:p失敗します。

以下は、コード内のフック 1 に対応するログ ファイルの抜粋です。

\l_tmpa_tl=\Foo {A,B,C} です。

私は、その拡張バージョンの RHS を期待していました=。なぜそうではないのでしょうか。また、それは可能でしょうか。

コード内のフック 2 に対応する出力は次のとおりです。

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

\Foo {A,B,C}FAIL は、中央の LHS に表示される展開+と RHS の等式をテストした結果です。この不一致はどこから来ているのでしょうか。

\documentclass{l3doc}
\usepackage{xparse}

\ExplSyntaxOn

\cs_new_protected:Nn \foo_str_compare:nn
{
  \exp_args:NNx \tl_set:Nn \l_tmpa_tl {#1}
  \tl_log:N \l_tmpa_tl % Hook 1
  \exp_last_unbraced:Nf % Hook 2
  \str_if_eq:nnTF
  {
    {\l_tmpa_tl}
    {#2}
    {PASS}
    {FAIL+#1+#2+}
  }
}

\NewDocumentCommand{\Foo}
{m}
{
  \seq_gset_from_clist:Nn \foo_seq {#1}
  \seq_use:Nnnn \foo_seq{,~}{,~}{~and~}
}

\NewDocumentCommand{\Test}{}
{
  \foo_str_compare:nn{\Foo{A,B,C}}{A,~B~and~C}
}

\ExplSyntaxOff

\begin{document}

\Test

\end{document}

答え1

文字列比較は、展開可能な素材に対してのみ実行できます。 文書コマンド は\Foo保護されており、 も使用していますが\seq_gset_from_clist:Nn、これは展開できません。 ( ではinterface3、星印が付いていない関数は展開できません。一般的に、代入やタイプセットを実行するものは展開できません。)

カンマリストの拡張可能なマッピングを使用するように書き直すと、

\documentclass{l3doc}
\usepackage{xparse}

\ExplSyntaxOn
\cs_new:Npn \foo_str_compare:nn #1#2
  {
    \str_if_eq:eeTF {#1} {#2}
      { PASS }
      { FAIL+#1+#2+}
  }

\NewExpandableDocumentCommand{\Foo}
{m}
{
  \int_case:nnF { \clist_count:n {#1} }
    {
      { 0 } { }
      { 1 } {#1}
      { 2 } { \__foo_two:w #1 \s_stop }
    }
    { \__foo_list:w #1 \s_stop }
}
\cs_new:Npn \__foo_two:w #1 , #2 \s_stop { #1 ~ and ~ #2 }
\cs_new:Npn \__foo_list:w #1 , #2 \s_stop
  {
    #1 , ~
    \int_compare:nNnTF { \clist_count:n {#2} } > 2
      { \__foo_list:w #2 \s_stop }
      { \__foo_two:w #2 \s_stop }
  }

\NewDocumentCommand{\Test}{}
{
  \foo_str_compare:nn{\Foo{A,B,C}}{A,~B~and~C}
}

\ExplSyntaxOff

\begin{document}

\Test

\end{document}

前述の通りegregの回答コード内には推奨パターンではないさまざまな構造があり、私はそれを避けてきました。

答え2

成功するには拡張性が必要なのに、拡張不可能な関数を使用しています。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\cs_new_protected:Nn \foo_str_compare:nn
 {
  \tl_log:e { #1 }
  \str_if_eq:eeTF {#1} {#2}
   {PASS}
   {FAIL+#1+#2+}
 }
\cs_generate_variant:Nn \tl_log:n { e }

\NewDocumentCommand{\Test}{m}
 {
  \seq_gset_from_clist:Nn \l_tmpa_seq {#1}
  \foo_str_compare:nn{\seq_use:Nnnn \l_tmpa_seq{,~}{,~}{~and~}}{A,~B~and~C}
 }

\ExplSyntaxOff

\begin{document}

\Test{A,B,C}

\end{document}

それに、あなたは を乱用しています\exp_args:...\exp_last_unbraced:...例えば、

\exp_args:NNx \tl_set:Nn \l_tmpa_tl { #1 }

より適切な書き方は

\tl_set:Nx \l_tmpa_tl { #1 }

また\str_if_eq:eeTF、完全な拡張を得るには、 にも注意してください。

「PASS」が表示され、ログファイルには、

> A, B and C.

による強制拡張によるものです\tl_log:e

関連情報