マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

LaTeX 上で色々と実装してみる話(ナベアツ編-1)

LaTeX 上で動く」色々なプログラミング言語を使って実装してみよう、という話。

まずは基本のナベアツから。問題は次の命令を実装すること。

  • \NabeAzz{<整数n>}: 1 から n までの整数の 10 進表記を順に空白区切りで出力する。ただし、整数が「3 の倍数である」または「(その 10 進表記に)数字 3 を含む」場合は、「アホなフォント」に変えて出力する。

「アホなフォント」で出力する命令は次のものを一貫して用いる。

\usepackage{type1cm}
% Computer Modern Funny Italic で出力する
\newcommand*\Aho[1]{{\usefont{OT1}{cmfr}{m}{it}\LARGE #1}}

出力結果は以下のようになるべきである。

TeX 言語
(参照:アレアレアレアレアレアレ

いわゆる「TeX on LaTeX」。なお、「LaTeX 上に TeX があるのじゃなくて TeX の上に LaTeX が乗っているのではないか」という指摘については右から左へ受け流すことにしよう。

[nebeazz-tex.tex]
\documentclass[a4paper]{article}
\usepackage{type1cm}
\newcommand*\AhoFont[1]{{\usefont{OT1}{cmfr}{m}{it}\LARGE #1}}
\makeatletter %!!!!!!!!!!!!!!!!!!!!!!!!! BEGIN TeX code
\newif\ifxx@aho
\newcount\xx@cnta
\newcommand*\NabeAzz[1]{%
  \xx@cnta=0
  \@whilenum{\xx@cnta<#1}\do{%
    \xx@ahofalse
    \advance\xx@cnta1 \@tempcnta\xx@cnta
    \divide\@tempcnta3 \multiply\@tempcnta3
    \ifnum\xx@cnta=\@tempcnta \xx@ahotrue
    \else \expandafter\xx@in@nabeazz@a\the\xx@cnta3\relax
    \fi
    \ifxx@aho \AhoFont{\the\xx@cnta}\space
    \else \the\xx@cnta\space
    \fi
  }%
}
\def\xx@in@nabeazz@a#13#2\relax{%
  \ifx!#2!\else \xx@ahotrue \fi
}
\makeatother  %!!!!!!!!!!!!!!!!!!!!!!!!! END TeX code
\begin{document}
\NabeAzz{40}
\end{document}

さて、これで TeX 言語の出番は終わり。以降は、LaTeX と指定のプログラミング言語のみを用いて実装することになる。

expl3
(参照:アレアレ

「未来の LaTeX」の実装言語(予定)である expl3 *1を用いて、完全展開可能になるように実装した。以前に作ったものを最新の expl3 の仕様に合わせて書き直した。((以前のコードで利用していた str_if_contains_char:nNTF(元々内部用だった)が廃止になっていて、完全展開可能で他に利用できるものがないので結局その部分を自前で実装した。完全展開可能性が不要ならもっと簡単に実装できる。))

[nebeazz-expl3.tex]
\documentclass[a4paper]{article}
\usepackage{xparse}
\usepackage{type1cm}
\NewDocumentCommand\AhoFont{m}{%
  {\usefont{OT1}{cmfr}{m}{it}\LARGE #1}%
}
\ExplSyntaxOn  %!!!!!!!!!!!!!!!!!!!!!!!! BEGIN expl3 code

\cs_new:Nn \zrxx_main:n
  {
    \int_step_function:nnnN { 1 } { 1 } {#1}
      \zrxx_process_step:n
  }
\cs_new_eq:NN \NabeAzz \zrxx_main:n

\cs_new:Nn \zrxx_process_step:n
  {
    \bool_if:nTF { \zrxx_int_is_aho_p:n {#1} }
      { \AhoFont { \int_to_arabic:n {#1} } }
      { \int_to_arabic:n {#1} }
    \c_space_tl
  }
\cs_new:Nn \zrxx_int_is_aho_p:n
  {
    \bool_if_p:n
      {
        \int_compare_p:nNn { \int_mod:nn {#1} { 3 } } = { 0 } ||
        \zrxx_if_contains_char_p:fN { \int_to_arabic:n {#1} } 3
      }
  }
\cs_new:Nn \zrxx_if_contains_char_p:nN
  {
    \bool_if_p:n
      {
        ! ( \tl_if_empty_p:n {#1} ) &&
        ( ( \token_if_eq_charcode_p:fN { \tl_head:n { #1 } } #2 ) ||
          ( \zrxx_if_contains_char_p:fN { \tl_tail:n { #1 } } #2 ) )
      }
  }
\cs_generate_variant:Nn \token_if_eq_charcode_p:NN { fN }
\cs_generate_variant:Nn \zrxx_if_contains_char_p:nN { fN }

\ExplSyntaxOff %!!!!!!!!!!!!!!!!!!!!!!!! END expl3 code
\begin{document}
\NabeAzz{40}
\end{document}

*1:ちなみに、TUG 2013 のスライドによると、「その言語」の名前が expl3 ということで良いらしい。