Pugs で Perl 6 入門 (3)

前回の記事から久しく時間が空いてしまいました。

前回ではPugsを使ってプログラムを動作させる方法を学びました。今回はPerl 6プログラムの書き始めですので,Perlらしくまずはファイルの入出力を取り扱うことにしましょう。

まず,試しに以下の readafile.pl を打ち込んで pugs readafile.pl と実行してみてください(ファイル名が違うと動きません)。readafile.pl のソースコードが画面に表示されたはずです。これはファイルを読み込んで出力するプログラムで,カレントディレクトリ内の "readafile.pl" というファイルの中身を表示します。

readafile.pl
#! pugs
use v6;

# ファイルを読み込みモード (read mode) で開く
my $in = open "readafile.pl";

# 一行ずつ読み込んで変数 $line に代入する
for =$in -> $line {
  # 末尾に改行をつけて変数 $line を出力する
  $line.say;
}

# ファイルを閉じる
close $in;

簡単な説明はコメントで書いていますが,それぞれ少し詳しく見ていきましょう。おっと,コメントの書き方をまだ説明していませんでした。# 記号を書くと,その行はそれ以降はコメントとみなされ,実行されません。Perl 6には様々なコメントの記法がありますが,たいていの場合は # で十分です。

ファイルのオープン

ファイルの中身を出力する手順は,

  1. ファイルをオープンする
  2. ファイルの中身を読み込む
  3. 読み込んだ文字列を出力する
  4. ファイルをクローズする

ですね。まずはファイルのオープンを見てみましょう。

ファイルのオープンは次のコードで行っています。

# ファイルを読み込みモード (read mode) で開く
my $in = open "readafile.pl";

まず,「my $in」を説明する必要がありますね。これは変数の宣言です。変数を使う際には必ず宣言をしなければなりません*1

my というのは正確には「レキシカルスコープを持つ変数の宣言」を意味するキーワードですが,単純に「変数を宣言するときは my を付ける」と覚えておけばOKです。それから $in という感じで識別子の前に $ 記号が付いていますね。Perlでは変数の前に記号(sigilと呼ばれています)が付き,一種の型を表しています。ただし型といっても,int型やdouble型というのではなくて,$scalar は1つの値を保持する変数(スカラー変数),@array は配列(リスト)を保持する変数(順序配列),&code は関数などを保持する変数という意味での型です*2。int型やstring型といった区別はないので,Perlの変数には数値や文字列などいろいろなものを代入することができます*3

open はファイルをオープンする関数で,引数としてファイル名のみを与えた場合,読み込みモード (read mode) でそのファイルを開きます。ファイルのオープンに成功すればファイルハンドルが返されます。ここでは,そのファイルハンドルを変数 $in に代入しています。

ファイルの中身を読み込んで出力する

ファイルの中身を読み込んで,さらにその文字列を出力する作業は次のコードで行っています。

# 一行ずつ読み込んで変数 $line に代入する
for =$in -> $line {
  # 末尾に改行をつけて変数 $line を出力する
  $line.say;
}

for 文はいわゆる foreach 文と呼ばれるもので,配列(リスト)から要素を一つずつ取ってきて処理する場合に使います。右矢印の後に変数名を書くと,その後のコードブロック(クロージャと呼ばれます)内でその変数を使って配列から取ってきた値にアクセスすることができます。例えば,

for 1, 2, 3 -> $num {
  $num.say;
}

とすると

1
2
3

と出力されます。これは,よくイテレータと呼ばれている仕組みです。ここではファイルの中身を一行ずつ取ってきて処理しようとしているのですが,処理したいものが単なるリスト(配列)でない場合,=$in という感じで変数名の前に = 演算子を置くことでイテレータとして扱うことができます。

for 文の中にある $line.say は $line の中身を改行を付けて出力しています。読み込んだものをそのまま改行を付けて出力すれば「改行が余分に多く付くのではないか?」と思いますが,Perl 6では入力はデフォルトでchompされる(末尾の改行を取り除くことはchompと呼ばれています)ので,$lineの最後には改行が付いていないので自分で改行を付けてあげないといけません。もし改行を付けたくない場合は print を使ってください。

なお,$line.say という記法を見て分かるとおり,sayは関数ではなくメソッドです。この場合は,文字列クラスのメソッドとなっています(これらはオブジェクト指向の用語ですが,分からない方はそういうものだと思って読み飛ばしていただいて構いません)。$line という変数には型がありませんが,データ自体に型があるので,ここらへんはよきに計らってくれるのです。もしメソッドが気に食わない場合は,同名の関数も提供されているので say $line というように記述しても動作します。

ファイルのクローズ

ファイルのクローズは次のコードで行っています。

# ファイルを閉じる
close $in;

close は与えられたファイルハンドルを閉じます。そのままですね。いちおう成功すれば真 (True) が返りますが,ここでは特に利用しないので戻り値は捨てています。

今回はここまで。次回はこれを発展させて自家製 cat コマンドを作ってみることにしましょう。

*1:Perl 5では標準では変数の宣言を行わずに変数を使うことができました。Perl 6では標準でPerl 5 における use strict; が有効になっていると考えられます。

*2:Rubyのようにスコープを表すわけではありません。

*3:Perl 6では変数を型付けする機能が導入されており,必要であれば my Num $number のように型を付けて変数を宣言することができるようになります。