以前よりアナウンスしているように7/21(金)にRubyの作者であるまつもとゆきひろ氏による講演会「楽しいプログラミング --オブジェクト指向スクリプト言語Ruby--」(主催:電子情報通信学会)を開催する。(場所は、総合理工学部3号館2階多目的ホール、時間は14:30-16:00である。)情報科学概論受講者は必ず参加すること。なお、当日はレポートのための用紙を会場で配布するので、その用紙に感想を200字程度にまとめて書いて提出すること。提出締め切りは7/25(火)の17:00とし、提出先は3号館10階の1017室の前に箱を用意するのでそれに入れることとする。
課題の提出具合によっては追加措置などを行う必要があることを事前にアナウンスしておいたが、結構な数の受講者が課題の提出をがんばった結果、問題のある受講者の人数がかなり少なくなった。よって、特別の追加措置は行う必要がなさそうである。以前に連絡したとおり、7/18(火)の段階で課題の提出状況をとりまとめ、単位取得に問題がある場合には提出状況の学生番号を赤字にしておくので、単位取得の意欲がある場合は未提出の課題に取り組むこと。(別途、提出すべき課題を指定する場合もある。)最終的な締切は7/25(火)の17:00とする。(それ以後の提出は無効となるので注意すること。)なお、今年度落とした場合の来年の再履修は、パソコンの数を考えると、教室で普通に受講できない可能性が高い。その場合には、自分で空き時間にwebテキストなどを参考に作業を行うしかないので今年度の状況よりもさらに不利になることを覚悟しておくこと。
6/20の講義において、Rubyによる表計算スクリプトを紹介した。その時にも説明したように、UNIX系の環境では、商用アプリケーションをビジネス用途に用いる伝統が無かったので、表計算のような作業も自分でスクリプトを組んで行うことが常識であった。前回は、そのような計算をどのようにして行うのかの手順だけを説明したが、本日はプリンタへの出力を考慮したTeX変換スクリプトを例として紹介する。おおざっぱな流れとしては、テキストで元のデータを用意し、Rubyで処理した後、TeXファイルとして出力し、印刷用のデータを作成する、という手順である。
元のデータは前回用いたものと同じ構成で以下のようなものとする。
品物 単価(円) 数量 りんご 300 5 みかん 40 6 キウイ 70 2
作業内容自体も前回と同様に上のデータに関して、各果物の金額を計算し、合計することとする。Rubyによるスクリプトのもっとも基本的な例を以下に示す。
スクリプト例
#!/usr/bin/ruby #spread.rb print '\documentclass{jarticle}', "\n" print '\pagestyle{empty}', "\n" print '\begin{document}', "\n" print '\begin{tabular}{|l|r|r|r|} \hline', "\n" total = 0 require 'jcode' file = open("spread-e.txt") while line = file.gets() line.chomp! ary = line.split(/\t/) if /^\D+$/ =~ ary[1] ary << "金額(円)" for i in 0..3 print ary[i] print " & " if i < 3 end print " \\\\ \n \\hline\n" else product = ary[1].to_i * ary[2].to_i total += product ary << product for i in 0..3 print ary[i] print " & " if i < 3 end print " \\\\ \n \\hline\n" end end printf "合計 & & & %d \\\\ \\hline\n", total print '\end{tabular}', "\n" print '\end{document}', "\n"
TeXの詳細については「論文作成術」の教科書を参照するとして、今回の作業に関しては、結果として出力されるファイルは以下のようなものになるので、それに関して解説しておく。
出力結果
\documentclass{jarticle} \pagestyle{empty} \begin{document} \begin{tabular}{|l|r|r|r|} \hline 品物 & 単価(円) & 数量 & 金額(円) \\ \hline りんご & 300 & 5 & 1500 \\ \hline みかん & 40 & 6 & 240 \\ \hline キウイ & 70 & 2 & 140 \\ \hline 合計 & & & 1880 \\ \hline \end{tabular} \end{document}
上にある{|l|r|r|r|}は表の列が4列であることを意味し、各列の両側に縦の罫線が入ること、文字の揃え方が一番左の列が左揃え (l) 、その他が右揃え (r) となることを示している。また、水平方向の罫線を引くためには、各罫線の場所で\hlineというコマンドが必要になる。表の中の要素は&で仕切られ、\\によりその行が終わり改行される。
このようなTeX形式の出力を行うことはRubyのprint文で変数の値を出力するときに一緒に出せばよいのだが、気を付けないといけないことが一つある。TeXの制御コードは基本的には\(バックスラッシュ)で始まる。しかし、Rubyでは\はその後に続く文字の意味を殺し、特殊文字として扱うように指定する記号である。(教科書、p.69)そのため、\が出てくるときにそれがTeXにおける\なのか、Rubyにおける\なのかにより、式展開させるかさせないかを決めておく必要がある。例えば、" "でくくった文字列中では\nは改行コードであるが、' 'のようなシングルクオートの場合、中に含まれる\nは改行コードとして展開されず、文字通りの\nを意味する。逆に、TeXの表中における改行コードである\\を出力するためには、\により\の意味を殺す必要があり、\\をダブルクオーテーション中で使うためには\\\\と4回並べる必要がある。奇数番目の\が偶数番目の\の特殊な意味を無効にし、ただの\としている。
このような式展開の有無を考えて、ダブルクオーテーションとシングルクオーテーションを使い分ける場合もあるが、例ではダブルクオーテーションによって囲んだ場合に、適宜バックスラッシュ記法をうち消すための\を挿入することも行っている。
実際の作業
今回の作業を行うに当たって注意することがある。教科書にも書いてあったようにRubyが正確に日本語を扱うためには文字コードがEUCかSJISである必要がある。ところが、教室のXEmacsのデフォルトがJISであるので、そのままのスクリプトでは日本語周りでエラーが出る可能性がある。よって、作成したスクリプトやデータファイルをEUCに変更する。手順は以下のようになる。
上記のスクリプトをXEmacs上で入力したら、一度、spread.rbというファイル名で保存する。そして、コード変換を以下のように実行する。
$ nkf -e spread.rb > spread-e.rb
上で、nkfは引数として与えたファイルの文字コードを推測してオプションで指定した 文字コードに変換するコマンドである。ここでeを指定しているのでEUCに変更する。そして、>で指定したファイル名でコード変換したテキストを保存する。同様に、元のデータファイルも以下のようにEUCに変更しておく。
$ nkf -e spread.txt > spread-e.txt
実際のスクリプトの実行は以下のようなコマンドにより簡単に行える。まずは、スクリプト本体に実行権限を与える必要があるので、
$ chmod +x spread-e.rb
としておき、
$ ./spread-e.rb
として、動作を試す。ここで、無事に上のTeXソースの内容が画面に出力されていればスクリプトの動作は大丈夫であるので以下のようにソースファイルを作成する。
$ ./spread-e.rb > spread.tex
これでspread.texというTeXソースが作成された。ここで、拡張子に注意すること。TeXでは拡張子として.texをソースファイルに付けておく必要がある。
TeXのソースファイルが無事にできたらコンパイル作業に入る。TeXはテキスト形式のソースファイルを解読して印刷用のdviファイルを作成し、プリンタに印刷するのが基本的な流れである。ここでは、以下のようにして行う。
$ platex spread.tex
これでエラーが無くコンパイルが終われば良いが、ソースに間違いがあるときにはエラーメッセージが表示され、処理が途中で止まる。その時には、エラーメッセージをよく読んでどこを直せばよいのか探す。次に、dviファイルの表示である。
$ ls
コマンドを実行してみるとわかるが、無事にコンパイルが終われば、作業中のディレクトリにはspread.tex、spread.dvi、spread.log、spread.auxという4種類のファイルができている。そのうちのspread.dviが印刷用ファイルであるので、以下のようにして画面に表示する。
$ xdvi spread.dvi &
このときだけ、コマンドの最後にバックグラウンド処理を示す&がついていることに注意。すべての作業に問題がなければ画面に目的の表が表示されるはずである。
このようにUNIX環境では表計算というジャンルが無く、自分でスクリプトとTeXを組み合わせて表示用ファイルを作ることが行われてきた。実際によく用いられる言語はAWKというスクリプト言語で、テキストの列ごとの処理などが得意な言語である。しかし、Rubyのような本格的な言語を利用して行ってももちろん構わない。
本日の課題はこちらへ。
約3ヶ月間に亘ってスクリプト言語のRubyを学習してきた。本来ならば新しく言語を学習するとなると最低でも1年、場合によってはもっと長くしないとなかなか身に付かないのが実情である。今回の授業の目的は、もちろんRubyの修得が行われればそれに越したことは無かったのであるが、それ以外の目的の方も大事であった。すなわち、計算機環境をコマンドベースで使用できるようになること、スクリプトを記述するために論理的に思考する能力と変数などの概念の把握、そして、表計算などの処理を通じたテキスト処理や文字コードの理解、である。
上記の内、最初のコマンドベースの作業はエレクトロニクスセミナーAとの連携で行ってきた。どのようなプログラミング言語を利用する場合でも作業はコマンドベースで行う必要がある(GUIのプログラミングであってもコードにコマンドを記述して作成していくことに違いない)ため、必須の要件であったが、あまり時間を割けなかった、というか、もっと楽しいことをやってもらおうと別のことに時間を使いすぎたこともあり、少なくない人数がもう少しという段階であろう。今後のC言語の授業でさらに学習して欲しい。
本格的な数学を学習する前に数値計算などを行ってもハードルが高いのでテキスト処理を中心としたスクリプト言語の学習はそれなりに意味のあることであったが、こちらも文字コードに関する説明は十分であったととは言えないかもしれない。文字コードはネットワークに利用に関しても重要な概念であるのでもう少しふれておきたかったが、現状の時間数ではいかんともしがたい。
最後に、なぜプログラミング言語を学習するのか、なぜRubyなのか、なぜLinux環境であるのか、などパソコン自体の初心者だと疑問に思うかもしれない。それに対する私の回答は授業の最初に言ったとおりである。言語はいくつか学習していくうちに共通部分や異なっている部分を理解したりできるし、自分の感覚に合ったものに出会うこともある。また、基本的には言語であるので、「習うより慣れろ」である。とにかくソースを自分で書くこと。ちょっとした処理をプログラミングにより実行させてみることから始めることが大事である。便利なツールがあふれている今日であるが、その中で同じことを何度も繰り返したり、煩わしい処理があったりする場合(例えば、数百通のメールの中から必要なメールアドレスや語句を検索するのに、いちいちメールを開いて探すのはおっくうである(はずである)。)もある。そういうときがプログラミング言語の出番である。また、計算だ処理だと肩肘張らずにHTMLなどから初めてみるのも良い。TeXも一つの言語であるので、レポートの作成など短いものから初めてみると論理構造などの学習にはもってこいの教材となるはずである。
ここでRubyを学習したのも何かの縁である。私の力不足により学習の効果が上がっていないとしたら弁解の余地はないが、今後の活用を期待している。