はじめまして(た)Perlさん その3

サブルーチン

関数ですな。
定義の仕方

sub サブルーチン名 {
  処理
}

呼び出し方

&サブルーチン名;
戻り値

戻り値を返すサブルーチン、返さないサブルーチンの区別はなく
サブルーチンはすべて値を返す。
サブルーチンの中の最後の計算の結果を自動的に戻り値にする。

sub hoge {
  2*3;
}
print &hoge;#6が出力される。
引数

引数はサブルーチンを呼び出すときに、
()の中にカンマ区切りで書いていく。これは
他の言語とかと同じ。
で、他の言語と違うのは関数定義のほう。
JavaScriptだと

function hoge(a, b) {
//処理
}

だけど
Perlは引数が@_に格納される。

sub hoge {
  ($a, $b) = @_;
  #処理
}
&hoge(1, 2);

とこんな感じにすると、各変数に引数が入るから以降の処理に
違和感がないな。

プライベート変数

今まで使ってた変数はどれもグローバルなものだった。
で、サブルーチンの中だけのプライベート変数の定義方法は?
ということで、方法はmyを使うそう。
で、スコープはブロック単位になる
上の例でいくと、$aと$bはグローバル変数になってしまっている。
これをmyをつけてレキシカル変数(という)にする。

sub hoge {
  my($a, $b) = @_;
  #処理
}
&hoge(1, 2);

そうすると、変数$aと$bのスコープはサブルーチンの中のみになる。

local演算子

myとほとんど同じようにプライベート変数を提供する。
でも、実はこいつの正体は、グローバル変数で、スコープの間、
値を置き換えるというもの。

myとlocalの違い

myはほんとにプライベートな変数。
localはグローバル変数を一時的に置き換えることで擬似的に
プライベート変数を作っている。

sub sub1 {
    my $b = "my";
    local $a = "local";
    &sub2;
    print "sub1:My: $b \n"; #$bは"my"となる。
    print "sub1:Local: $a \n";#$aはlocalとなる。
}
sub sub2 {
    print "sub2:My: $b \n";#なにも表示されない。
    print "sub2:Local: $a \n"#$aはlocalとなる。
}
&sub1;
print "Global: $a \n";

ここで注目はsub2の出力。
$bは"my"とならず、$aは"local"となっている。
これは、
local演算子つけた$aはsub1の間は、グローバル変数$aを"local"に置き換えてる
だから、sub1から呼んでいれば(sub1の処理が終わるまでは)グローバル変数
にアクセスして"local"って値をみれる。
一方、my演算子つけた$bはグローバル変数とは別の場所に格納されているので
sub2からはみることができない。というかsub2の$bはグローバル変数の$bを
だしてる。
なんとなくわかった。

return演算子

普通にある。
サブルーチンの途中で処理戻したいときとかに使う。

sub hoge {
  my($x, $y) = @_;
  if($x > $y){
    return 1;
  }
  -1;
}

みたいに最後に評価される方はreturnを省略するほうが
Perlらしいとのこと、これはちょっと慣れないなぁ。

アンパサントの省略

組み込み関数と同じ名前でなければ省略できる。

use strictプラグマ

プラグマって?
コードの扱いに関してコンパイラに与えるヒントのこと。

use strictプラグマって?
コンパイラによいプログラミング規則を強要するべきであると伝える。

よくわからん!
strictと聞いて真っ先にXHTMLを思いだしたんだけど、
これつけることによってプログラミング規則をある程度縛って
変なことやるとコンパイラが警告だしておこるようにするってことかな。

ハッシュ

他の言語と考え方は一緒。

要素へのアクセス
$hash{key}

とする。

ハッシュ全体を表すには。

配列の@のようにハッシュは%をつける。

ハッシュの代入
%hash = (key1, value1, key2, value2, key3, value3);

とkeyとvalueを交互に書いていく。わかりにくい。
とおもいきや、=>を使ってかけるようだ。

%hash = (
  key1 => value1,
  key2 => value2,
  key3 => value3,
);

最後に余計に,がついてても問題ない。

ハッシュ関数
keys
ハッシュ内のキーをリストで返す。
values
ハッシュ内の値をリストで返す。
each
キーとバリューのペアのリストを返す(whileループでつかう)
exists
キーが存在するかを真か偽かで返す。
delete
ハッシュから指定されたキーを消す。

ハッシュはキーを追加したりすると、最適化が行われるため、
keys,values,eachで返す値の順番は保証されていない。