マクロツイーター

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

それでも TeX でプログラミングしたい人のための何か (2)

前回の続き)

解説の方針とか

当初、「このそれぞれの項目について詳細を説明する」という感じで記事を書いていこうと思っていた。しかしそうするとどうしても重たい解説が長く続くことになり、読者の負担になる恐れがある。ちょうど「普通の言語のプログラムを TeX のものに書き換える」手順を披露することが(少しだけ)流行しているようなので、ここでは、自分が(先に述べたように)プログラムを変換するときに従っている手順について解説していくことで、先に挙げた「TeX の癖」についての具体的な説明をすることにしたい。いわば「私の TeX プログラム変換環境」の解説である。

ステップ 0 : 変換元の「普通の」プログラム

題材として使用するのはコレである。

……うん。なんか楽しそうだったから。

元のプログラムを作る

変換元のプログラムを「普通の」言語で作る。別にどの言語でもよいので、自分の使いやすいものを選ぼう。私は一番慣れているのは Perl であるが*1TeX に変換する目的でプログラムを作る場合は Lua を使う場合が多い。(理由は後で判る。)ここでも Lua を使用する。*2

本当はこの段階で「TeX が苦手な処理(例えばビット演算とか)を避ける」ことに注意した方がよい。でも特に初心者は何が「苦手な処理」かは知らないだろうから余り気にする必要はない。もし例えば三角関数が必要になったのなら、そのためのパッケージを援用すればよいだけである。

というわけで、特に気にせずに普通に Lua のプログラムを書くと次のようになった。

-- eltaso.lua

-- alpha_name : アルファベットの日本語読みの仮名表記
alpha_name = {
  --※ Luaは配列添字を普通は1から始めるので, 添字ゼロの要素を
  --   別に指定している.
  [0] = "ぜっと", -- alpha_name[0] は「ぜっと」
  "えー", "びー", "しー", "でー", "いー", "えふ", "じー",
  "えいち", "あい", "じぇー", "けー", "える", "えむ", "えぬ",
  "おー", "ぴー", "きゅー", "あーる", "えす", "てぃー", "ゆー",
  "ぶい", "だぶりゅー", "えっくす", "わい"
  -- alpha_name[1] は「えー」, ……
}
-- digit : 漢数字(1〜9)
digit = {
  [0] = "", -- ゼロを空文字列にしておく
  "一", "二", "三", "四", "五", "六", "七", "八", "九"
}

-- knumeral(n) : 整数n(1〜9999)の漢数字表記
function knumeral(n)
  -- 整数nを4桁の十進表記で表し, それを文字毎に分割する
  -- n=123 なら '0', '1', '2', '3' となる
  local dm, dc, dx, di = 
    ("%04d"):format(n):match("^(.)(.)(.)(.)$")
  local km = knum_pos(dm, "千")
  local kc = knum_pos(dc, "百")
  local kx = knum_pos(dx, "十")
  return km .. kc .. kx .. digit[tonumber(di)]
end
function knum_pos(d, u)
  d = tonumber(d)
  if d == 0 then return ""     -- 0×百 は無出力
  elseif d == 1 then return u  -- 1×百 は「百」
  else return digit[d] .. u    -- 2×百 は「二百」
  end
end

-- eltaso_name(n) : 整数n(1〜9999)に対する「えるたそ名」
function eltaso_name(n)
  return knumeral(n) .. "反田" .. alpha_name[n % 26]
end

-- eltaso_name(n) : 整数n(1〜9999の範囲)に対して, 1からnの各整数
-- に対する「えるたそ名」を出力する.
function eltaso(n)
  if n > 9999 then n = 9999 end
  for j = 1, n do
    print(eltaso_name(j))
  end
end

-------- メイン
eltaso(1000)

このプログラムを Lua インタプリタで実行すれば結果が得られる。もし手元の TeX システムに LuaTeX が含まれているならば、texlua というコマンドを Lua インタプリタとして使用できる。すなわち、コマンドシェルで

texlua eltaso.lua

を実行すればよい。これで次のような出力が得られる。((なお、Lua は特定の文字コードに依存しない言語なので、本来なら、eltaso.lua を記述する漢字コードは何でもよくて、実行した際に「同じ漢字コードでの」出力が得られるはずである。ところが、シフトJISを用いた場合、漢数字の〈十〉が所謂「ダメ文字」(下位バイトが 0x5C)なのでエラーになってしまう。Windows の人は、ソースファイルを UTF-8 で保存した上で「texlua eltaso.lua > out.txt」のようにファイルに書き出して出力のファイルをエディタで見る、等の手順を踏む必要がある。))

一反田えー
二反田びー
三反田しー
四反田でー
五反田いー
……(992行省略)……
九百九十九反田けー
千反田える

(はい、このような出力を得るのが「えるたそ」プログラムの目的です。)

さて、この Lua プログラムを TeX(on LaTeX)プログラムに変換する作業を始めよう。

さっさと例のネタを済ませる

……できた!!

% LuaTeX 文書; 文字コードは UTF-8
\documentclass[a4paper]{ltjsarticle} % LuaTeX-ja だよ
\usepackage{luacode}
\begin{luacode*}
-- (以下 eltaso.lua の中身をコピペする)
-- alpha_name : アルファベットの日本語読みの仮名表記
alpha_name = {
--…………(中略)…………
--(↓最後の部分を少し変更する)
function eltaso(n)
  if n > 9999 then n = 9999 end
  for j = 1, n do
    tex.write(eltaso_name(j), "\par") -- print を tex.write に変えた
  end
end

-- 「メイン」のコードを削除
\end{luacode*}

%%<*> \eltaso{<整数>} : えるたそ。
\newcommand*{\eltaso}[1]{%
  \par
  \directlua{ eltaso(\number#1) }% Lua関数呼出
}
\begin{document}
\eltaso{1000}
\end{document}

もちろんこれは単なるネタである。ただし実際には、「Lua で書けば LuaTeX でそのまま動かせる」ということがプログラムの作成の作業上で助けになることもあったりする。まあここでは深入りせずに先に進もう。

(続く)

*1:TeX ではない。念のため。

*2:PerlRubyPython 等のスクリプト言語のどれかの知識を持つ人なら Lua のプログラムは「直感的に」理解できると思う。Lua 自体の解説が目的ではなく、どの言語を用いた場合でも手順は変わらないので、Lua の文法は気にしないのがよいだろう。他の言語の使用者にとって判り難い「Lua の癖」については適宜プログラム中のコメントに示した。