Perl初歩の初歩

プログラミング言語Perlの初心者のためのわかりやすい解説ブログ(を目指しています)

リサイクルの心がけ…サブルーチンの話

2009-06-01 15:07:37 | ルールを覚えよう

プログラムを作っていくと、何度も同じことをしなくてはならないことがあります。
プログラムのはじめのほうで出てきた一連のやりとりが、プログラムの中盤にも終盤にも出てきたりして、そのたびに同じコードをコピーした結果、あちこちに同じ一連のコードがあるという状況はけっして良くありません。もし、その部分を変更しなくてはいけなくなったときに、何か所も直さなくてはいけなくなりますから、のちのち不便になります。
そこで、サブルーチンの出番です。
これは、一連のコードをまとめておくプログラムの固まりです。

「起きる」
「シャワーを浴びる」
「朝ごはんを食べる」
「仕事する」
「昼ごはんを食べる」
「仕事する」
「夕ごはんを食べる」
「シャワーを浴びる」
「寝る」
(一日の終わり)

こんなプログラムがあったとき、「シャワーを浴びる」と「仕事をする」が2か所ずつあります。おなじものは一緒にしてしまおうというのがサブルーチンです。

「起きる」
→サブルーチンAへ
「朝ごはんを食べる」
→サブルーチンBへ
「昼ごはんを食べる」
→サブルーチンBへ
「夕ごはんを食べる」
→サブルーチンAへ
「寝る」
(一日の終わり)

サブルーチンA「シャワーを浴びる」
サブルーチンB「仕事する」

メインの流れとは別に、離れたところにまとめて置いておいて、メインのほうにはサブルーチンを見るようにと指示するわけです。

実際には次のようになります。

$x = 1;
$y = 2;
&tashizan;
$x = 3;
$y = 4;
&tashizan;
exit;

sub tashizan {
  print $x + $y;
}

まず、$x に 1、$y に 2 を入れます。
次にサブルーチン tashizan を実行します。
サブルーチン tashizan は $x と $y を足したものを表示します。
サブルーチンが終わったら前のところに戻ります。
今度は、$x に 3、$y に 4 を入れます。
そして、もう一度、サブルーチン tashizan を実行して、
exit でプログラムを終了させます。

サブルーチンは sub tashizan { } の部分です。
sub につづけて、お好みのサブルーチンの名前をつけます。
サブルーチン使うときには、&とサブルーチンの名前という形になります。


サブルーチンに何らかの値を渡したい場合があります。
たとえば、先程の例でいえば…

「起きる」
→サブルーチンAへ
→サブルーチンC(朝)へ
→サブルーチンBへ
→サブルーチンC(昼)へ
→サブルーチンBへ
→サブルーチンC(夕)へ
→サブルーチンAへ
「寝る」
(一日の終わり)

サブルーチンA「シャワーを浴びる」
サブルーチンB「仕事する」
サブルーチンC「ごはんを食べる」(時間帯)

このように「ごはんを食べる」でひとつにまとめて、メインのほうでは朝昼夕の時間帯だけを指定すると楽なわけです。

このような感じをプログラムにしてみると次のようになります。

$x = 2;
$y = 3;
$z = &kakezan($x, $y);
$z = &kakezan($z, $y);
print $z;
exit;

sub kakezan {
  my ($a, $b) = @_;
  my $c = $a * $b;
  return $c;
}

サブルーチン kakezan では、受け取った2つの数字をかけた答えを返します。

$x に 2、$y に 3 を入れ、kakezan に渡します。
戻ってきた答えが $z に入ります。
次に、$z と $y をもう一度 kakezan に渡し、その答えを $z に入れます。
結果は、2 * 3 * 3 ですから、18 になります。

&kakezan( ) と書き、( ) の中にサブルーチンに渡したいデータを、(複数ある場合は)カンマ区切りで入れます。

サブルーチンのほうでは、my ($a, $b) = @_; という書き方でデータを受け取って、return で返しています。
@_ という特殊な配列に、受け渡されたデータが入っています。
配列ですから、配列の1番目は $_[0] ですし、2番目は $_[1] と表現できます。
つまり、次のような書き方もできます。

my ($a, $b) = @_;

my $a = $_[0];
my $b = $_[1];

my $a = shift @_;
my $b = shift @_;

my $a = shift;
my $b = shift;

上の4種類はどれも同じです。
shift は、配列の先頭からデータを1つ取り出す命令です。
この時、特殊な配列 @_ は省略できるというルールがPerlにはあるので、単に shift で受け取れるわけです。
筆者もはじめて こういう使い方をする shift を見たときには「ナンデ?」って思いました。

$a、$b の前についている my は、この変数はこのサブルーチンの中でしか使いません、ということを主張しています。もし、このサブルーチン以外で $a や $b を使っていた場合、それは別の変数として扱うことになります。
したがって、わかりやすいように $a や $b としましたが、$a が $y で $b が $x であってもなにも問題は起こりません。my さえついていれば、サブルーチンの外と中とで同じ変数名が使え、別のものとして扱ってくれるわけです。

ちなみに、サブルーチンへ受け渡すデータ、サブルーチンで受け取るデータのことを、プログラム業界では、「引数(ひきすう)」と言います。
サブルーチンから返ってくるデータを「戻り値(もどりち)」と言います。

また、サブルーチンのことを、「ユーザー定義関数」と言ったり、単に「関数」と言う人もいます。


わかれ道を作ってこそ…条件の話

2009-05-30 12:05:02 | ルールを覚えよう

プログラムが最初から最後まで1本道だったら、いつも同じ答えが出てしまい、応用がききません。
やっぱり、プログラムにはいろいろな場合場合によって、状況を変えるわかれ道が必要で、そうでなくてはなりません。

Perlでわかれ道を作るには次のようにします。

if ($hour == 6) { print "おはようございます"; }

if は もし~なら という英語で、if の後に条件があって、もし条件に合えば、{ } の中を実行し、もし条件に合わなければ、{ } は無視して次に進むようになっています。

上の例では、もし $hour という変数が 6 だった場合のみ、「おはようございます」と表示され、6 以外だった場合は、何も表示されないという意味になります。

== は 数字を比較するときに使う特殊な記号(比較演算子)で、同じかどうかを調べます。

if ($hour != 6) { print "6時ではありません"; }

!= も 数字を比較するときに使う特殊記号で、違うかどうかを調べます。
上の例では、$hour が 6 ではないときに、{ } の中を実行します。

if ($hour < 6) { print "まだ6時になってません"; }
if ($hour > 6) { print "もう6時は過ぎました"; }
if ($hour <= 6) { print "6時か6時前ですね"; }
if ($hour >= 6) { print "6時以降ですね"; }

不等号を使って比較することもできます。


文字を比較するときには別の記号を使います。

if ($shumi eq 'マラソン') { print "何km走れますか?"; }
if ($shumi ne 'マラソン') { print "走るのは嫌いですか?"; }

eq は 文字が同じかどうかを調べます。英語のイコール(equal)を略したんでしょうね。
ne は 文字が違うかどうかを調べます。not equal の略でしょう。


さらに、2つ以上の条件を使うには次のようにします。

if ($hour >= 6 && $hour <= 9) { print "おはようございます"; }
if ($hour <= 4 || $hour >= 18) { print "こんばんは"; }

$hour が 6時から9時の間のときに、「おはようございます」を表示します。
$hour が 4時より前、あるいは 18時以降のときに、「こんばんは」を表示します。

条件と条件の間に && を入れることで、両方の条件を満たすかどうかを、
同様に間に || を入れることで、どちらかの条件を満たすかどうかを調べます。

これらを使って複雑な条件を作ることができます。

if ($hour >= 6 && $hour <= 8 && ($shumi eq 'マラソン' || $shumi eq 'ジョギング')) { print "さあ、朝のランニングに行きましょう"; }

6時から8時の間で、かつ、趣味がマラソンかジョギングのときに表示されます。

このとき、優先度に注意してください。
>= や <= や eq が最優先で、次に && 最後に || という順番があります
上の場合、2番目の && よりも マラソンとジョギングをつなぐ || を優先したいので、( ) でくくっています。

もし、カッコがなかった場合は、
 6時から8時の間でかつ趣味がマラソン、あるいは、趣味がジョギング
という条件になってしまいます。

 


呼べば応える名前付き配列…連想配列の話

2009-05-25 21:40:52 | ルールを覚えよう

スカラー変数($)と配列(@)について説明してきましたが、今度は名前付きの配列とも言うべき、「連想配列」の話です。別名「ハッシュ」とも言います。

連想配列は、名前(キー)と値の組み合わせを覚えてくれる入れ物です。

%menu = ('今日のオススメ' => 'サバのミソ煮', 'Aランチ' => '野菜炒め定食');
$menu{'Bランチ'} = '豚のしょうが焼定食';
$menu{'スペシャル'} = '幕の内定食';

上の例では、まず、%menu という連想配列に、今日のオススメ という名前の サバのミソ煮 と、Aランチ という名前の 野菜炒め定食 を入れています。
次に、Bランチ という名前の 豚のしょうが焼定食 と、スペシャル という名前の 幕の内定食 を %menu に追加しています。

連想配列の全体をあらわす時は、頭に % をつけます。
また、連想配列に入っている1つ1つのデータをあらわす時は、$ と { } を使います。

$x = '今日のオススメ';
$y = 'Aランチ';
print $menu{$x};
print $menu{$y};

上記のように、$x に 今日のオススメ、$y に Aランチ が入っている場合、
$menu{$x} は、サバのミソ煮 になりますし、$menu{$y} は、野菜炒め定食 です。

%youbi = ('Sun' => '日曜日', 'Mon' => '月曜日', 'Tue' => '火曜日');
%youbi = ('Sun', '日曜日', 'Mon', '月曜日', 'Tue', '火曜日');
%youbi = qw(Sun 日曜日 Mon 月曜日 Tue 火曜日);

上の3つはすべて同じです。
データを連想配列にまとめて入れる時には、通常見やすいように => で、名前と値の組み合わせを表現しますが、単に , カンマ で区切るだけでも構いません。
カッコの前に qw をつけて、 ' や , を省略することもできちゃいます。


データを並べて入れておく箱…配列の話

2009-05-18 14:36:22 | ルールを覚えよう

Perlの変数には3種類ある、というのは以前のページで説明しました。
ここでは、そのうちのひとつ「配列」についてのお話です。

配列は、数値や文字などを順番に並べて置いておく入れ物です。

@kamoku = ('国語', '算数', '理科', '社会');
@channel = (1, 3, 4, 6, 8, 10, 12);
@list = ($x, $y, $z);
@iroiro = ('国語', 3, $x, "$y点です");
@month = (1..12);
@kara = ();

上の例では、
@kamoku には、国語、算数、理科、社会の順に文字が入ります。
@channel には、1 3 4 6 8 10 12 の順に数字が入ります。
@list には、$x と $y と $z の中に入ってるデータが順に入ります。
@iroiro のようにデータを入れることができます。
@month には、1 から 12 までの12個の整数が順に入ります。
@kara は 配列の中身を空っぽにしています。

配列にデータを入れる時には、( )で囲み、それぞれを , で区切ります。
@month の .. は特殊な表現で、数字が1つずつ増えていくことを表します。

@kamoku = ('国語', '算数', '理科', '社会');
$n = @kamoku;
$x = $kamoku[0];
$y = $kamoku[2];
push(@kamoku, '英語');
$n = @kamoku;

上の例では、最初に @kamoku に4教科を入れます。
次に、$n に @kamoku の中に入っているデータの個数(要素数)を入れます。この場合は $n には 4 が入ります。
$x には @kamoku の中の 0 番目のデータが入ります。この場合は「国語」。
$y には @kamoku の中の 2 番目のデータが入ります。この場合は「理科」。
配列の順番は 0 から始まります。
$配列名[番号] の形で、配列の中の1つを取り出すことができます。

push(配列, データ) は 配列の最後にデータを加える命令です。
@kamoku の「社会」の後ろに「英語」を加えています。

最後にもう一度要素数を数えます。
ひとつ前に「英語」が加わっていますので、$n には 5 が入ります。

@month = (1..12);
@tuki = ();
foreach my $m (@month) {
  push(@tuki, "$m月");
}

配列 と foreach とは、切っても切り離せない関係です。
上の例では、1 から 12 の数字を、ひとつずつ順番に $m に入れ、それぞれに「月」を加えた文字を、@tuki に入れています。
@tuki には、「1月」から「12月」までの文字が入ります。


おまけ:
配列にデータを入れるときに、カンマで区切ったり ' をつけるのが面倒なことがあります。そんなときに重宝するのが qw( ) です。

@kamoku = ('国語', '算数', '理科', '社会');
@kamoku = qw(国語 算数 理科 社会);

上の2行ともまったく同じ意味です。
qw を カッコの前につけると、カッコ内の文字は スペース で区切っていることになるのです。すっきりするでしょ?


数字や文字などを1つだけ入れる器…スカラー変数

2009-05-04 14:07:14 | ルールを覚えよう

Perlの変数には3種類ある、というのは前のページで説明しました。
ここでは、そのうちのひとつ「スカラー変数」についてのお話です。

スカラー変数は $a $x $abc $osara $date など、頭に $ をつけてあらわして、数字や文字などの情報を入れておく入れ物です。

スカラー変数に情報を入れるには、スカラー変数に続いて = を書き、そのあとに入れたい数字や数式や文字などを書きます。

$a = 1;
$y = $x * 10;
$abc = 'ABCDEFG';
$osara = '肉じゃが';
$date = "$year年$month月$day日";

上の例では、

$a に 1 を入れる
$y に $x を 10倍したものを入れる
$abc に ABCDEFG という文字を入れる
$osara に 肉じゃが という文字を入れる
$date に $year $month $day の中に入っているものを 年月日の文字とともに入れる

という意味になります。

文字を入れる場合には、' または " で囲む必要があります。
' で囲んだ場合にはそのまま、" で囲んだ場合は変数の中身が入ります。

たとえば

$nedan = 980;
$price1 = '$nedan';
$price2 = "$nedan";

とした場合、$price1 と $price2 には別のものが入ります。
$price1 は ' で囲んでありますので、そのまま $nedan という文字が入ります。
$price2 は " で囲んでありますので、980 という文字が入ります。

スカラー変数では、数字と文字を区別しません。

$x = '001234';
$y = $x * 10;
print $y;

上の例では、最初に $x に 001234 という文字を入れています。
しかし、次の行でその文字を10倍にしています。
$y には 12340 が入ります。
$x に入っている 001234 を 1234 という数字とみなして計算しているわけです。
ただし、 $x 自体は変化せずに 001234 のままです。

では、次の場合はどうなるでしょうか。

$x = 'abc';
$y = $x * 10;
print $y;

$x には abc という文字が入ります。
しかし、次の行でその文字を10倍にしています。
abc を無理やり数字とみなした場合 0 となります。
したがって、$y は 0 です。

スカラー変数には、文字や数字のほかに、他の変数やサブルーチンも入れることができます。
しかし、ここは初心者のためのページなので、そのことについては別の機会で。


です、ますをしっかりする…文法の話

2009-04-30 21:27:27 | ルールを覚えよう

日本語にも文法があるように、Perlというプログラミング言語にも文法が存在しています。
Perlは他の言語とくらべて比較的自由な言語となってはいますが、それでも守らなくてはいけない数多くの決まりがありますので、しっかり覚えていきましょう。

$a = 1;
$b = 2;
$c = $a + $b;
print $c;

$a = 1 は a という名前のスカラー変数に、数字の 1 を入れたことを意味します。こうすることで、今後、 $a と書いたときそれは 1 を表します。

ひとつの文の終わりには ; (セミコロン) を必ず書きます。

これはプログラムを実行する際に、改行が無視されるため、どこからどこまでがひとつの文かわからなくなるのを防ぐために、文の最後にセミコロンが必要となるのです。

$a
=
1
;

上のように極端に別の行に書いたとしても、 $a = 1; と同じ意味となります。

逆に、$a = 1; $b = 2; と横に並べて書いても、セミコロンさえ入っていればなんら問題はありません。

とはいえ、セミコロンのうしろに改行を入れておくほうが見やすいのではないでしょうか。


データを運ぶ入れ物が必要だ …変数の話

2009-04-30 17:52:41 | ルールを覚えよう

プログラム上では、データを入れ物に入れておく必要があります。食事をするときには料理をお皿に盛るのと一緒です。お皿に盛らなくてもナベという入れ物に入っていることもあるでしょう。

Perlには入れ物が3種類あります。

$ と @ と % です。

$osara とか @obento とか %menu というふうに、それぞれの記号のうしろに名前をつけて使います。自分でお好みのアルファベットを使って入れ物の名前をつけることができるわけです。

$ という入れ物の中には、ひとつの物しか入れることができません。

$osara には 「肉じゃが」や「ほうれん草のおひたし」など、それぞれ1品料理が入ってるわけです。

@ という入れ物には、複数の物を入れることができます。

@obento には「ご飯」も「タコさんウインナー」も「お漬け物」も入れることができるわけです。

% という入れ物にも複数の物を入れられますが、入れたものにさらに名前をつけることができます。

%menu にはたくさんの料理がありますが、これをください、と料理名を指定すれば好きなものが出てくるわけです。

入れ物のことを変数、$ を スカラー、@ を配列、% を 連想配列またはハッシュと呼びます。

$osara = "肉じゃが";
@obento = ("ご飯", "タコさんウインナー", "お漬け物");
%menu = ("今日のオススメ" => "サバのミソ煮", "Aランチ" => "野菜炒め定食");

上の例のようにすることで、それぞれの入れ物に料理を入れることができます。