現場でのやっつけPerlに学ぶサブルーチン作成のアプローチ

# 対象読者
- プログラムはかじっているものの、**Perl**という言語をよく知らない。
- 同じ「P」から始まるなら「Python」一択っしょ！**Perl**って何ですか？**古文書ですか？**やば！とか思っているし、実際に口に出している。
- そんな毒を吐いて、イキり散らしていたら**Perlの現場にアサインされてしまった**。
- 「リファレンス」「コンテキスト」という言葉の響きだけで頭痛・めまい・嘔吐の症状が認められ、**Perlを出来るだけ触らないように**と医者から言われている。

# はじめに
**Perl**は[ラリー・ウォール](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%AA%E3%83%BC%E3%83%BB%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB)によって開発された動的型付け言語です。
「**There's More Than One Way To Do It.（TMTOWTDI）**」
というスローガンが示す通り
「やり方は幾らでもある」という思想を元にした
**設計の柔軟性**に富んだ素晴らしい言語です。

C言語やsed、awk、シェルスクリプトなど古き良きレガシーな知見を取り入れつつ
更にはクロスプラットフォームかつ軽快、という挙動を以って
「**[CGI](https://ja.wikipedia.org/wiki/Common_Gateway_Interface)**と言えばPerl」「**文字列処理（正規表現）**と言えばPerl」
という確固たる地位を確立しながら
Webシステムを始めとしたITアーキテクチャの発展を後押ししつつ
**Python**や**Ruby**、並びに**Javascript**へ与えた言語的な影響は少なくない
というそんな素晴らしい言語なのです。

「あそこのレンタルサーバは**Perlが使えない**から別の所にしよう。」

そんな理由がホームページ開設のロケーション判断基準になるほど
かつてのPerlはプログラム言語適用シーンにおける選択肢として
**なくてはならないもの**だったのです。

今はどうでしょう？

「**嫌い**な言語」ランキング、
「今これを勉強しても**稼げない**言語[^1]」ランキング、
といった不名誉なワーストクラスタにおける**上位ランカーの常連**であり、
現実的な生産性・可読性の面からみても
お世辞にも**「よい言語」とは評価されにくい**現状のようです。

ただ、待ってください。
たったの一側面だけを見て
**Perlという言語を見切ってしまう**のは余りにも早計過ぎやしませんか？

たとえば、プログラム言語の起こりから
現在まで極めつくしている**仙人**のような先達が言うならともかく
プログラム言語の**初学者が軽々にPerlを切り捨てる**のは
単純に**ただただ勿体ない**と思う次第であります。

一生懸命、汗水垂らして、何なら血涙も伴いながら深堀りしないとわからないような
**プログラム言語のそれぞれの思想、その骨子の一端がPerlには詰まっているのに**。

また、Perlが結果として嫌われてしまうシーンの一つとして
仕事でどうしても**Perlを扱わざるを得なくなった**事
に起因するケースが挙げられますが
「めんどくさい」「やりたくない」「なんでこのご時世にPerlなんか」
といった**負の感情にただ身を委ねる**のではなく
どうしたってPerlを触る事が不可避なのであれば
Perlという言語そのものに対して**前向き**に付き合うのがベターだと考えます。
（そういった姿勢はPerlに限った話ではありませんけども。）

にしたって実際の現場に身を置いた際に
**足の指でタイピングしたのかな？**と思うような既存のPerlプログラムを読んでいると
「**あぁ…もうこれ以上Perlと関わりたくねぇなぁ…**」
とナチュラルに思う事が多々あるのは確かです。
下手したらその現場には綺麗なソースコードなんて1バイトもないかもしれません。
読むのも骨だし、ましてや直すのなんて一層骨でしょう。

ですが、10年以上、ましてや仕事でPerlを触った事のなかった著者が
実際に現場でPerlを触ってみて至った結論は
**「Perl現場はサブルーチン作成までの基礎知識で十分戦える」**
でした。

つまり、まとめると本稿では

- Perlはいい言語！CGIはいい文化！
- だからPerlが無慈悲に足蹴にされるのは何となくモヤモヤする！コツ教えたろ！
- でもそこまでPerlに詳しくないし、そもそも**深堀りしたくもないし…**（震え声）

といった**心理的葛藤**を著者自身の為に紐解くとともに

「**Perlをゼロから追求したい**」
「Perlの開発実績を基にして**他の言語にもその実地経験を活かしたい**」

といった方の為にも、現場でPerlと「**とりあえず**」うまく付き合えるコツなんぞを
共有させて貰えたらこれ幸いと思い立ち筆を執りました。

以下、本稿は**物語形式**で進行します。
無駄に**長い**です。
ご承知おきください。

# プロローグ
～～内示当日～～

新人「（よーし。もう長かった新人研修も終わりに近いぞ！）」

新人「（配属はゴリゴリの**開発志望**で出したし、
　　　ウチの会社は**Pythonの現場がほとんど**と聞いているし、
　　　キャンパスで培った俺の**ロジカルな地頭**を発揮できる時が来たようだな！）」

新人「（Pythonの本は一通り読んだし、
　　　自分である程度**ポートフォリオ**も組み立てられたし、
　　　色々な**ワークショップ**も経て、
　　　有識者の**フィードバック**も得ている。
　　　足りない実地経験は**競プロ**に積極的に手を出して補充もしている！）」

新人「（無論、Pythonの現場に**ジョイン**したい事は会社にも伝えているし、
　　　**研修の実績と評価は上々**との自負もある！）」

新人「（あとは現場に出て、**実践的なPythonの経験値**を積むだけだ！）」

**部長「あー、新人君」**

新人「は、はい！何でしょうか！」

部長「君の、配属先ね…」

新人「はい！」

部長「**パ…**」

新人「（焦らさないで！早く！早くちょうだい！）」

部長「**Perl**」

新人「イエス！パイソン！**……え？今、なんて？**」

部長「**Perl**」

新人「」

# 冒険の始まり
～～着任初日～～

？？？「…新人君…新人君！？」

新人「（zzz）ハッ…はい！」

？？？「まったく…最近の若い子と来たら…
　　　　寝る暇があったら１バイトでも多くコードを書いて欲しいものですよ。」

新人「…すいません。」

？？？「このPerlを愛し、Perlに愛された男、
　　　　**陰照 眼鏡（いんてり めがね）**の感性からすると考えられませんよ。
　　　　（メガネクイ）（メガネの縁キラリン）」

新人「（陰照先輩の説明は**密度が濃すぎて**付いていけないんだよな…）」

新人「（Perlだからモチベーションも上がらないし…）」

陰照「では、おさらいです。」

### Perlの変数型
Perlは大きく「スカラ」と「スカラでない」型に分かれます。

「スカラ」とは「文字列」「数値」など一般的な変数値に加えて
「リファレンス（後述）」を示します。

「スカラでない」とは「配列」や「ハッシュ」など、特殊な変数の型を指します。

変数を宣言するには**「Sigil（シジル、シギル）」**と呼ばれるプレフィックス記号を
変数の頭に置く必要があります。

**Sigil**
$ : スカラ（文字列・数値・リファレンス）
@ : 配列
% : ハッシュ

また、変数の宣言時には**my**をつけましょう。

```perl:sample.pl
# 数値
my $num = 0;

# 文字列
my $str = 'aiueo';

# 配列
my @arr = (1, 2, 3);
print $arr[1];    #「2」を出力

# ハッシュ
my %hash = ('a'=>4, 'b'=>5);
print $hash{'a'}    #「4」を出力
print $hash{a}    #添え字の囲み文字（シングルクォーテーション）は省略可能
```

### リファレンスとデリファレンス

リファレンスとは何でしょうか？
ポインタのようなものです。（メガネクイ）
その変数が格納されている**メモリアドレス**そのものを指します。

変数のリファレンスを得るには
変数の頭に「\（バックスラッシュ）」を付与します。

```perl:sampl.pl
# 配列のリファレンスを得る方法
# 文字列が格納された配列
my @arr = ('a', 'b', 'c');

# 「\（バックスラッシュ）」をつけてリファレンスを得る。
my $ref_arr_1 = \@arr;
```

リファレンスはただのアドレスですから、
リファレンス経由で変数の中身にアクセスする際には
**アロー演算子（->）**を使用する必要があります。

```perl:sample.pl
# 配列
my @arr = ('a', 'b', 'c');

# 配列にアクセス
print $arr[0];    #'a'を出力
print $arr[1];    #'b'を出力
print $arr[2];    #'c'を出力

# 配列のリファレンスを宣言
my $ref_arr = \@arr;

# アロー演算子で配列にアクセス
print $ref_arr->[0];    #'a'を出力
print $ref_arr->[1];    #'b'を出力
print $ref_arr->[2];    #'c'を出力
```

このように、リファレンスを経由して元のデータにアクセスする事を
**デリファレンス**と呼びます。

デリファレンスの方式としては
この他にデリファレンス修飾子を使うやり方があります。

**デリファレンス修飾子**
${} : スカラ
@{} : 配列
%{} : ハッシュ

```perl:sampl.pl
# 配列
my @arr = (1, 2, 3);

# 配列のリファレンス
my $ref_arr = \@arr;

# 配列のデリファレンス
my @deref_arr = @{$ref_arr};

# 配列のデリファレンス（構文糖）
# 中身が単純値の場合、{}を省略可能
my @deref_arr2 = @$ref_arr;

# 配列のデリファレンス（構文糖）
# 配列のリファレンスから直接格納値へ一直線にアクセス。
# これは${$ref_arr}[0]という意味である。
my $val = $$ref_arr[0];
```

またリファレンスを利用して**無名配列**、**無名ハッシュ**を作成する事もできます。
名称を伴う変数を基にしてリファレンスを生成するのではなく、
いきなりリファレンスから宣言するので**「無名」**という事ですね。

```perl:sampl.pl
# 無名配列の宣言。()ではなく[]を使う。
my $ref_arr = [1, 2, 3];
print $ref_arr->[0];    #「1」を出力
# 無名配列のデリファレンス。
my @deref_arr = @{$ref_arr};
print $deref_arr[0];    #「1」を出力

# 無名ハッシュの宣言。()ではなく{}を使う。
my $ref_hash = {a=>4, b=>5};
print $ref_hash->{a};    #「4」を出力
# 無名ハッシュのデリファレンス。
my %deref_hash = %{$ref_hash};
print $deref_hash{a};   #「4」を出力 
```

### コンテキスト
～～復習中～～
カタカタ　カタカタ（コーディング中）

新人「（うぅ…記号が多い…頭が痛い…**吐き気がする**…）」

新人「あれ？」

陰照「どうしました？新人君」

新人「今、教わった内容をprintで確認していたんですが、見え方がおかしいんです。」

陰照「どれどれ」

```perl:sinjin.pl
my @arr = ('a', 'b', 'c');
# １
print @arr;
print "\n";
# ２
print @arr."\n";
```

新人「１のprintでは「**abc**」と出力されるのに
　　　２のprintでは「**3**」と出力されました。
　　　どういう事ですか？」

陰照「フフフ…それが**コンテキスト**です。」
　

##### コンテキストとは？

**「文脈」**という意味です。
Perlでは前後の記述の**「文脈」**を解釈し、
その**文脈評価の一環として変数を扱います**。

では「文脈」とは何でしょうか？
次の日本語の「文脈」を考えてみましょう。

『彼は外出していなかった』

前後の文章や背景がわからない状態だと
この日本語は2通りに解釈できます。

A. 彼は既に出かけており、**家にいない状態**である。
B. （例：出かけているであろうという予想に反して）彼は**家にいる状態**である。
　　もしくは、過去の時点で「家にいる状態」であった。

このように「いなかった」という文節に対して
どういう意味で捉えるか、解釈するか、
この評価軸を**コンテキスト**と言います。

##### コンテキストの種類

Perlのコンテキストには
大きく「スカラコンテキスト」と「リストコンテキスト」の
2種類があります。

以下にそれぞれの代表的なコンテキストを挙げます。

＜スカラコンテキスト＞
- スカラ変数への代入　`my $hoge = 'aaa';`
- 比較演算子の左項と右項 `$hoge < $fuga`
- ifの条件部　`if(EXPR)`

＜リストコンテキスト＞
- 配列への代入　`my @hoge = (1, 2, 3);`
- リスト表記の内部　`(1, 2, 3)`
- サブルーチンの引数　`subroutine(EXPR)`


ともあれ、先ほどの答えを申し上げますと
「配列はリストコンテキストで評価される場合は配列そのものとして解釈されるが
　配列がスカラコンテキストで評価される場合は**配列の要素数**として解釈される」
という事です。

```perl:interi.pl
# 配列
my @arr = ('a', 'b', 'c');
# １ リストコンテキスト
#    リスト（配列）を出力する。
print @arr;
print "\n";
# ２ スカラコンテキスト
#    文字列との結合が求められている為
#    Perlインタプリタはこれをスカラコンテキストで評価し
#    配列の要素数が返却される。
print @arr."\n";
```

ちなみに、配列の要素数を得たい場合は
**「$#」での配列表現が配列末尾のインデックスを示す**事を利用し
表現する事も可能です。
合わせて覚えておくとよいでしょう。

```perl:interi.pl
# 配列
my @arr = ('a', 'b', 'c');
# 配列の要素数（代入によるスカラコンテキストでの評価により要素数を得る）
my $cnt_arr = @arr;
print $cnt_arr;    #「3」を出力
# 配列末尾のインデックス
print $#arr;    #「2」を出力
# 配列の要素数
print $#arr + 1;    #「3」を出力
```

陰照「こんな感じです。わかりましたか？」

新人「はい…（何となくはわかったけど、全然付いていけていない…）」

陰照「新人君は他言語での開発経験があると聞いていますので
　　　早速、実地でPerlをゴリゴリ開発して頂きます。」

新人「いきなり！？」

陰照「えぇ。**時間も人手もありません**ので。」

新人「（やれる気がまったくしない…）」

陰照「あと、教えた内容についてはほんの触りなので、時間を見つけて
　　　自分でPerlの学習をしておいてください。
　　　そうですね。最低限、ここらへんは一通り読んでおいて欲しいですね。」

ドン

[初めてのPerl 第7版](https://www.oreilly.co.jp/books/9784873118246/)
[続・初めてのPerl 改訂第2版](https://www.oreilly.co.jp/books/9784873116280/)
[プログラミングPerl 第3版 VOLUME 1](https://www.oreilly.co.jp/books/4873110963/)
[プログラミングPerl 第3版 VOLUME 2](https://www.oreilly.co.jp/books/4873110971/)

新人「全部で2000ページ以上あるんですが…」

陰照「それが何か？」

新人「」

陰照「Perl道はそんな甘くないですからね…（ﾆﾁｬｱ）」

新人「ヒィッ！」

# 冒険の道しるべ
～～着任一か月後～～

カタカタカタカタカタカタカタカタ…

新人「（疲れた…）」

新人「（ろくな**仕様書も設計書もない**し…）」

新人「（既存コードは**何書いているかよくわからない**し…）」

新人「（コードによっても**書き味はバラバラ**だし…）」

新人「（やっている事と言えば**コピペ＆改変**がせいぜい…）」

新人「（目の前の作業に追われて**参考書を読む気力すら沸かない**…）」

新人「（Perlだしこんなもんでいいのかな…）」

新人「（次の現場で頑張ればいいか…）」

新人「それにしても陰照先輩、今日は遅いな。休みかな？」

？？？「**Perlの泣き声が聴こえるな**」

新人「！？いつの間に後ろに！？アナタは？」

？？？「俺の名前は遣付 太郎（やっつけ たろう）。
　　　　今日から君の面倒を見ることになった。」

新人「え？陰照先輩は？」

遣付「**アイツは死んだ。**」

新人「は？」

遣付「Perlと深く関わり過ぎたんだ。闇に飲まれてしまった。」

新人「どういう事ですか？」

遣付「ヒトとしては生きているがな。詳しくは言えない。
　　　**鉄格子に囲まれている**状態だとだけ言っておこう。」

新人「で、でもどうするんですか。
　　　次のリリース…えっと、バージョン**１５３２**ですね。
　　　もう時間もないし、陰照先輩のタスクもあったのに…」

遣付「安心しろ。その為に俺がここに来た。
　　　業務仕様はすべて頭の中に入っている。」

新人「よかった。じゃあPerlもお詳しいんですね。」

遣付「**全然。**」

新人「え？今なんと？」

遣付「Perlはやった事ない。今さっき[Perl入門ゼミ](https://tutorial.perlzemi.com/)をざっと読んできたところだ。」

新人「えぇぇぇぇぇぇ！？」

### 課題の炙り出し（As-is）

新人「い、いやいや、Perlを知らないで大丈夫なんですか？」

遣付「大丈夫だろう。」

新人「だろうって…」

遣付「よし。まずは現状整理だ。認識が正しいか一応確認させてくれ。」

新人「わかりました…（大変な事になったぞ。**本当に大丈夫か？この人。**）」

##### 見えている課題
１．Perlプログラムの仕様書・設計書がない。
２．Perlに詳しい人がいない。（いなくなった。）
３．Perlを作らなくてはいけない。

遣付「まず大きい所でこんなもんだな。」

新人「はい。その通りです。」

遣付「…加えて、ズバリこうだな。」

４．既存のPerlコードが**読み辛い。**しかも書き味がバラバラ。
５．Perlコードとして**何をどう書けば正解なのかがわからない。**
６．なので終始、「読み辛いけど、動く事は担保されている」であろう
　　既存Perlコードの**コピペ**に追われている。
７．コピペが主力なので、そもそものアルゴリズムやサブルーチンの
　　**構造を組み直す事も考えたくない。**
８．結果として**一つのサブルーチンがものすごく長くなる。**
９．自分で書いたコードですら**読み直したくない。**
１０．総じてPerlへの**モチベーションが低い。**

新人「（ギクッ！！）…恐れ入ります。その通りです。」

遣付「君の書いたコードも含めて既存コードは一通り、確認させて貰ったよ。」

新人「（うぅ…怒られそう。）」

遣付「でも、**しょうがない。**」

新人「え？」

遣付「上に挙げた１～３までは**どうしようもない前提**だ。
　　　君に限らず誰かが頑張ったところですぐにどうにかなる問題でもない。
　　　出来上がったスパゲッティはスパゲッティでしかない。
　　　それに塩をかけたり、水で洗ったり、こねたりした所で
　　　スパゲッティである事は変えられんさ。
　　　**作り直しでもしない限りね。**」

新人「はぁ…」

遣付「もし、万が一、ユーザにとって唸るほどの金が突然産まれて
　　　**『よし、このPerlコードを全部作り直そう』**
　　　となったとする。まかり間違って。億兆分の一の奇跡が起こって。
　　　**起こらない。**
　　　現実的には絶対にそんな奇跡は起こらないんだけど
　　　仮の話だ、まずそう仮定させてくれ。」

新人「はい。」

遣付「そうなった時、もし君なら**Perlで作るか？**」

新人「作らない…と思います。」

遣付「そうだろう？
　　　だから１～３までは過去の事象。変えられないただの出来事。
　　　自分が与り知らない過去の経緯にWhyを求めたり、
　　　現時点で自分がPerlを触ることにWhyを求めても仕方ないさ。
　　　**不毛なだけだよ。**
　　　ここまではいいかな？」

新人「はい。大丈夫です。」

遣付「よし。それじゃあ、次に**どうあるべきか**を考えてみよう。」

### 求められるシステムとあるべき自分（To-be）

遣付「それにしても、バージョン１５３２か…
　　　よくもこんなにPerlのシステムを長々と運用してきたものだな。」

新人「えぇ。とんでもないです。」

遣付「これからも当分はこの**変態的なバージョニング**が続くんだろうな。」

新人「…」

遣付「だからここのシステムのあるべき姿っていうのは単純だ。
　　　**動きゃいい。**それだけだ。
　　　どんなにつまんねぇ要求仕様に対しても粛々と改造を施され
　　　必要なシステムとして運用される限り稼働し続けて
　　　寿命を全うすればいいさ。」

新人「そう…ですね。」

遣付「**君はどうだ？**」

新人「え？」

遣付「君のあるべき姿だ。」

新人「自分のあるべき姿…」

遣付「**コピペマシーンになる事ではない**だろう？」

新人「自分は…」

新人「自分は…できれば他の言語で開発がしたいです。」

遣付「ふむ。」

新人「その為にも何か**潰しが利く形**で知見を広げられればと考えています。
　　　汎用的と言いますか…。
　　　**色々な武器を持っていて、更にそれらを自在に使いこなせる状態**…。
　　　うまく言えないですが、それがあるべき姿かと思います。」

遣付「なるほど。
　　　では、Perl開発はその**潰しが効く形で知見を広げるには向いていない**と？」

新人「正直…はい。そうです。向いていないと思います。」

遣付「いいだろう。」

### 本当にするべきこと（To-do）

遣付「君は**根本的に勘違いをしている。**」

新人「Perlに対してですか？」

遣付「いや、もっと大きな観点だな。**言語に対して**というべきか。」

新人「どういう事でしょうか。」

遣付「**アルゴリズム**という言葉は知っているな。」

新人「はい。これですね。」

>
アルゴリズム（英: algorithm [ˈælgəˌrɪðəm]）とは、数学、コンピューティング、言語学、あるいは関連する分野において、問題を解くための手順を定式化した形で表現したものを言う。算法と訳されることもある。
「問題」はその「解」を持っているが、**アルゴリズムは正しくその解を得るための具体的手順および根拠を与える。さらに多くの場合において効率性が重要となる。**
コンピュータにアルゴリズムをソフトウェア的に実装するものがコンピュータプログラムである。人間より速く大量に計算ができるのがコンピュータの強みであるが、その計算が正しく効率的であるためには、正しく効率的なアルゴリズムに基づいたものでなければならない。
（出典：[Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0)）
>

遣付「そう。そして**アルゴリズムを具現化したものがプログラム**とも言える。」

新人「はい。それが何か…？」

遣付「これを逆にする事で大きな齟齬が生まれる。
　　　**プログラムを具現化する為のものがアルゴリズムである**と。」

新人「？？？同じじゃないんですか？」

遣付「プログラムとアルゴリズムだけのスコープであればそれでいいさ。
　　　でもWikipediaにもある通り、アルゴリズムは**広義な言葉**だろう？
　　　**アルゴリズムがプログラムの為だけにあるとは限らない**という事だよ。」

新人「うーん…なるほど。」

遣付「では聞こう。Perlはアルゴリズムに対して**どういう姿勢**を取っている？」

新人「**There's More Than One Way To Do It.（TMTOWTDI）**ですか？」

遣付「そう。問題はそこなんだ。」
　

#### 「TMTOWTDI（やり方は幾らでもある）」に対する誤謬

遣付「There's More Than One Way To Do It.（TMTOWTDI）は
　　　決して**誤ったスローガンではない。**
　　　むしろPerlのAPIは**設計の自由度を広げる**事に努めているように思う。」

新人「では何が問題だと？」

遣付「よし。ではあらためて、課題の４番と５番を振り返ってみよう。
　　　ちなみに６番以降は４番５番に大きく起因する内容なのでもう**忘れて結構**だ。」

>
４．既存のPerlコードが**読み辛い。**しかも書き味がバラバラ。
５．Perlコードとして**何をどう書けば正解なのかがわからない。**
>

遣付「どうだ？
　　　こいつらはTMTOWTDIの**賜物**か？それとも**弊害**か？」

新人「弊害…だと思います。」

遣付「何故こんな事が起きたんだろう？」

新人「やり方が**あり過ぎる**からですかね。」

遣付「半分正解だ。
　　　やり方は幾らあってもいい。
　　　でも**好き勝手に書いてはダメ**という事さ。」

新人「うーん、耳が痛いですね。」

遣付「どれだけ設計の間口が開かれているのか、
　　　つまり**設計の自由度**は言語のポテンシャルによるのかもしれない。
　　　そういった意味でPerlは十分な設計の自由度を有している。
　　　ただ、**どう設計するのかはエンジニアの責任でしかない**という事だね。」

新人「なるほど。
　　　確かに**自分で書いたコードの書き味がバラバラ**な事も往々にしてあります。」

遣付「特に、複数人での開発プロジェクトになると**致命的**になる。
　　　今がまさにそうだろう？
　　　色んな人間が好き勝手にコードを書いた顛末がこれだ。」

新人「おっしゃる通りだと思います。」

遣付「じゃあ、逆に**より対極**にある観点を考えてみるとしよう。
　　　君の好きな**The Zen of Python**を思い出してみるといい。
　　　本質的なニュアンスはちょっと違うかもだが、言葉だけに注目してくれ。」

>
There should be one-- and preferably only one --obvious way to do it.
一つの（願わくは一つだけの）明確な手段があるはずだ。
>

新人「なるほど。TMTOWTDIとは**真逆**な印象を受けます。」

遣付「極端に言うなら**『やり方は一つしかない（一つであるべき）』**
　　　という考え方だね。
　　　これだとどうだ？
　　　**実際のPerl開発に耐えられるだろうか？**」

新人「何となく厳しい気がしますね。
　　　何が何でもやり方が一つだけしかないのであれば、
　　　コードはその分見やすくなるかもしれませんが、生産性も落ちる気がします。」

遣付「その通り。
　　　コーディングの自由度を全部殺すと、逆に生産性が落ちてしまう。
　　　でも設計の自由度は担保したい。
　　　先にも言った通り、
　　　**『幾らでもあるやり方の中から優れたやり方を選択するのはエンジニアの責任』**
　　　だからね。」

新人「うーん…難しい。」

遣付「だが、これらを解決する**たった一つの優れたやり方**が存在する。
　　　設計の自由度も生産性もそこそこ担保するやり方が。」

新人「えっ。それは何ですか？」

遣付「それがアルゴリズムの為のアルゴリズム。**標準化**だ。」

#### 標準化とは

新人「標準化？」

遣付「そう。言葉の定義を確認してみよう。」

>
標準化（ひょうじゅんか、英語：standardization(スタンダーダイゼーション)）という用語は、**文脈によって様々な意味**を持つ。「標準（standard）」という用語には、相互運用のための広く**合意されたガイドライン**という意味が含まれ、「標準化」はそのような**標準を確立する過程**を指すのが一般的である。
（出典：[Wikipedia](https://ja.wikipedia.org/wiki/%E6%A8%99%E6%BA%96%E5%8C%96)）
>

新人「これも随分と**広義**な言葉のようですね。
　　　Perl開発においてはどういう意味で捉えればよいでしょうか？」

遣付「言葉通りと言えば言葉通りだけどな。
　　　開発を進めるに当たって
　　　『こんな風にコーディングしていきましょう』という**やり方**を
　　　あらかじめメンバー間の**合意**の元で決める。
　　　それをルールとして『標準化仕様』や『コーディング規約』といった形で
　　　共有・遵守すればよいだけだよ。」

新人「『好き勝手にコーディングできなくなる』のはよいと思います。
　　　ですが、**やり方を狭めるという事による弊害**はないのでしょうか？」

遣付「いい質問だ。
　　　標準化というのはルールを決めるという事自体も大事なんだけど
　　　それ以上に**過程をシンプルにする**というのも大事な目的の一つなんだ。
　　　厳密に、厳格に、限界までルール付けするのであれば
　　　それは**Perlの言語仕様と変わらない**だろう？」

新人「それは確かに。」

遣付「だから、**ある程度**のパターン化・カテゴリ化を施す事で
　　　コーディングの方式をより少ない選択肢の中から選べるようにする。
　　　これで**どうやって作ったらよいかわからない**という暗中模索の状態に陥る事も
　　　ある程度、回避できるわけだ。」
　　　
新人「なるほど。確かに。
　　　お恥ずかしい話、コピペする時は
　　　コードのauthorを見たり、コードの読み易さを見たりして
　　　**コピペ元として適切かどうか判断**していたりもしましたが
　　　何となく『標準化』の方がよほど効率が良さそうですね。」

遣付「そうだ。
　　　好き勝手に書かれたコードだと、
　　　その人が**どんな理由**で、**どんな目的**で、はたまた**どんな気分**で
　　　結果として**どのようなアルゴリズムに至った**末に書いたのかが伺い知れない。
　　　下手したら、機嫌によって書き味が変わる人かもしれないしな（笑）」

新人「そんなコードもなくはないです。（笑）」

遣付「さて、まとめだ。
　　　前置きが長くなったが、要は**標準化こそTodo**という事だ。
　　　君の知見を広げてみせる為にも
　　　具体的な標準化の手段の話に移ろうと思うが
　　　ここまでは大丈夫かな？」

新人「えっと…そうですね。質問が**３つ**あります。」

遣付「よろしい。聞かせてくれ。」

#### アルゴリズムの為のアルゴリズム

新人「一番最初に言っていた
　　　**『アルゴリズムの為のアルゴリズム』**とは何でしょうか？」

遣付「アルゴリズムというのはWikipediaにも書いてある通り
　　　言ってみれば**手順、手続き**の事だ。
　　　そしてこうも書いてあるな。
　　　**『多くの場合において効率性が重要となる』**と。」

新人「はい。」

遣付「そして**アルゴリズムがプログラムの為だけにあるとは限らない**とも言った。」

新人「えぇ。そうでした。」

遣付「システムを構築する時にはプログラムが必要となる。
　　　そしてそのプログラムを作るときにはアルゴリズムが不可欠だ。
　　　ただ**システムは作って終わりではない。**」

新人「あ。**プログラムを書いた後のアルゴリズムも大切**という事でしょうか。」

遣付「その通りだ。
　　　システムを保守・運用する際にもアルゴリズムという概念は存在する。
　　　**どう効率的にシステムを保守し運用していくか**という考え方だ。」

新人「なるほどー。」

遣付「そして保守という活動の中には当然のように、
　　　プログラム改修も含まれているよね？」

新人「はい。」

遣付「という事は、**効率よくプログラムを保守する為のアルゴリズム**という
　　　考え方も大事になってくるわけだ。
　　　これは**コードを動かすためのアルゴリズム**ではなく
　　　ややこしい言い方をするのであれば
　　　**『コードを動かすためのアルゴリズム』
　　　を保守しやすいようにどう建て付けるかのアルゴリズム**
　　　という事になる。」

新人「はい。何となくわかります。
　　　要は**プログラム改修しやすい方がより良い**という事ですね。」

遣付「そういうことだ。」

新人「理解しました。」

#### 標準化の適用範囲

新人「では2つ目を。
　　　今現在、Perl開発は私を含めて**2人**で行っています。」

遣付「そうだな。」

新人「**少人数でもやる必要はあるのでしょうか？**
　　　2人くらいであれば都度確認するくらいでもよいのでは…」

遣付「**やるべき**だ。
　　　むしろ**1人でもやるべき**だ。」

新人「1人でも！？」

遣付「あぁ。君はさっき自分で言っていたな。
　　　**『自分で書いたコードの書き味がバラバラ』**になる事があると。」

新人「あ」

遣付「そこに『コーディングする際の迷い』なり
　　　『書き味の粒度のバラつき』があって、
　　　保守しにくくなる可能性があるのであれば
　　　それは保守というスキームにとって
　　　**効率的なアルゴリズムではない**んだ。」

新人「なるほど…
　　　あ、でも**どのソースに対して**標準化を徹底すればよいのでしょうか？
　　　**過去に遡ってのソースコード修正は現実的でない**と伺いましたが…」

遣付「**今からでいい。**」

新人「**これから作るものにだけ**という事でしょうか。」

遣付「そうだ。
　　　標準化仕様に『●年●月●日から施行』とでも書いておけばよい。」

#### 標準化の優先度

新人「なるほど。では3つ目です。
　　　これが一番聞きたかった事なのですが…
　　　標準化が何となく大事、という事は
　　　ニュアンスだけかも知れませんが、理解できたかと思います。
　　　今やっているやり方よりはマシとも。
　　　ただ、ここまで**開発が切羽詰まっている中**で
　　　**どれだけ優先度を上げて標準化の策定に臨むべき**でしょうか？」

遣付「そうだな。時間は有限だもんな。」

新人「はい…」

遣付「答えは**最優先**だ。」

新人「えぇぇ！？」

遣付「何か問題でも？」

新人「先ほど『標準化仕様』や『コーディング規約』が形として必要って…
　　　そんな時間ありませんよ…」

遣付「おいおい。勘違いしてもらっては困る。
　　　何も、**恭（うやうや）しい厳（おごそ）かな仕様書（笑）**
　　　を作れって言っているわけではないんだ。」

新人「へ？」

遣付「ぶっちゃけ、**メモ帳でいい**。
　　　そしてさっきも言ったな、**シンプルでいい。**
　　　ルールが本質的に共有できるのであれば**体裁は要らん。**
　　　体裁を気にする仕様書なんざ**クソ**だ。」

新人「時間をかけなくてよいって事ですか？」

遣付「そうだ。」

新人「でも、全てのルールをリストアップするのは無理じゃないですか？
　　　適用範囲が『これから作るもの』にだけって言っても…」

遣付「うん。**全てのルールを最初にリストアップする必要はない。**
　　　全てリストアップできるのであればそれはそれで望ましいが
　　　あまり時間をかけられないのであれば、
　　　**適宜、追加なり変更なり**していけばいい。」

新人「それだと書き味がどんどんズレていきませんか？」

遣付「違うんだ。
　　　これから作るソースも含めて
　　　**全ての書き味を揃えて進んでいく事が目的ではない**よ。
　　　**書き味が、同じ形に収束していく事に意味がある**んだ。」

新人「…なるほど！」

遣付「プログラムに必要なアルゴリズム。
　　　標準化に必要なアルゴリズム。
　　　これら、アルゴリズムの効率性は常に100%であるとは限らない。
　　　だが、より100%への改善を目指し、**高い効率性を保守**していく。
　　　これは**プログラムも標準化も変わらない**よ。」

新人「やれる気がしてきました！」

# 冒険の心得

遣付「よし。それでは具体的な標準化の内容について触れていこう。」

新人「お願いします。」

遣付「その前に…君は**サブルーチンを自前で作った事**はあるか？」

新人「実は…数えるくらいしかなくて。
　　　しかも簡単なモノしか書いたことはないです。」

遣付「なるほどな。
　　　では記念すべき**最初の標準化**はこう銘打とうじゃないか。」

### サブルーチン作成の十三か条

新人「十三か条…！」

遣付「安心してくれ。一つ一つはとても**シンプル**な内容だ。」

新人「ホッ…ちなみに、策定するのはサブルーチンに関連する事柄だけですか？」

遣付「初版だし、最低限の**基本文法**についても入れておくよ。
　　　あとは適宜、追加なり変更なり、章立てを組み替えたりしていこう。」

新人「承知しました！
　　　って、でも
　　　**何故、あえてサブルーチンを標準化のスコープとしている**んですか？」

遣付「これはあくまで個人的な考えではあるけど
　　　**サブルーチンを自前で作る事がPerlを理解する為の最善の取っ掛かり**
　　　であるように思う。
　　　リファレンスやコンテキストといった
　　　基本的な概念に対する最低限の理解が必要になってくるし
　　　**標準化を自分で建て付ける練習**にもなるしね。」

新人「はぁ…なるほど…」

遣付「それに、**サブルーチンを新規に作る事を嫌ったせいで
　　　鬼のように長くなってしまったサブルーチン**を
　　　これ以上、読み直したくはないだろう？」

新人「それは…もう！ホントに！」

遣付「ハハハ…それじゃ早速やっていこう。
　　　繰り返しになるけど、以降で説明する標準化の内容は**ほんの一例**だ。
　　　継続的に**標準化の内容を充実させるのは自分自身**
　　　という意識を忘れないでくれ。」
　

#### 第一条：まず「記号」に悩んだらPerldocを見よう。

新人「これは…何ですか？」

遣付「標準化、というよりは**初心者向けの心得**みたいなものだね。
　　　Perlのソースを読んでて**記号が多い**と思った事はないかな？」

新人「むしろ**記号しかない**と最初は思っていました…」

遣付「だよね。
　　　Perlはとても記号が多い言語だ。
　　　**表現方法が豊富**と言えば聞こえはよいが
　　　反面、**混乱を招く**要素になっているとも言える。」

新人「確かに。」

遣付「ただこればっかりは覚えてもらうしかない。
　　　コーディングしながら感覚で覚えた方が早いと思う。」

新人「でも全部覚えるのは大変じゃないですか？」

遣付「みっちり**隅から隅まで覚える必要はない**さ。
　　　言ったろう？**感覚で何となく**でいいのさ。」

新人「感覚…」

遣付「そう。
　　　例えば、$はスカラ、%はハッシュ、**/がたくさん出てきたら正規表現**、
　　　それくらいの識字感で最初は十分だ。」

新人「なるほど。」

遣付「そこで**Perldoc**だ。
　　　PerldocはPerl公式のWeb公開されている**言語仕様書**だね。
　　　関数のAPI仕様だけでなく、Perlの基本ポリシーや文法、データ型、
　　　正規表現、演算子に至るまであらゆる仕様がドキュメント化されている。」

[Perldoc（英語）](https://perldoc.perl.org/)

新人「すごいですね…でも英語か…」

遣付「英語が読めるのであれば本家の英語版を読むのがベストだ。
　　　ただ英語が読めなくても大丈夫。
　　　[一般社団法人 Japan Perl Association（JPA）](https://japan.perlassociation.org/)の監修の元で
　　　日本語化されたサイトもちゃんとあるんだ。」

[Perldoc（日本語）](https://perldoc.jp/)

新人「あ、これなら安心です。」

遣付「ただ、バージョンは気を付けるようにな。
　　　本家Perldocのバージョンは2019年8月時点で5.30.0が最新だが
　　　日本語化のバージョンは5.26.1が最新だ。」

新人「日本語化の方が少し古いんですね。」

遣付「そう。だから、最新のPerlを使う際には英語版を見た方がよいね。
　　　幸い、この現場は5.10.1という**10年前の骨董品**を採用しているから
　　　どっちでもいいけど。」

新人「ハハハ…」

遣付「なので、以降の説明では日本語版のサイトを引用していくよ。」

新人「わかりました。
　　　…あれ？この[目次](https://perldoc.jp/index/core)にある
　　　**perlintroとかperlsynとかのカテゴリは何者**ですか？」

遣付「それはただのエイリアスだね。
　　　Perl概要はperlintro、Perl文法はperlsyn、みたいに
　　　**カテゴリを示す略称の文字列**がPerlドキュメント内で定められているようだよ。」

新人「特に意味はないという事ですか？」

遣付「意味をそこまで気にしなくてもよいけど、
　　　覚えておくと、ググる時とかに手っ取り早いかもね。
　　　あ、**文法調べたいから「perlsyn」って検索する**か、みたいな。」

新人「なるほどー。
　　　でも、このPerldocもすごい内容量ですね。
　　　**参考書くらいのボリューム**はあるんじゃないですか？」

遣付「そうだね。
　　　だから**記号**という観点で参照するのであれば
　　　初手は**演算子（perlop）**から見ていくのがよいと思う。」

[perlop(5.26.1)](https://perldoc.jp/docs/perl/5.26.1/perlop.pod)

新人「演算子だけでも、ものすごい量だ…」

遣付「そう。
　　　ただ**記号の意味**を見たことあるのとないのとでは、
　　　既存ソースコードを読むスピードが変わってくるので
　　　**最低限、演算子は一通りざっと抑えるくらいはしておいた方がよい**。
　　　perlopが読み辛い、概要だけ知りたい、という事であれば
　　　[外部サイト](https://tutorial.perlzemi.com/blog/20161005147566.html)で概要を掴むというのも最初はアリだろう。」

新人「むむむ…なるほど。」
　　　
遣付「記号の早見という意味では公式でも[チートシート](https://perldoc.jp/docs/perl/5.26.1/perlcheat.pod)があるにはあるんだけど
　　　見やすいとは言えないね。
　　　だから、`$`や`&`や`%`といったよく使う記号について
　　　自分で**チートシートを作って目に付く場所に置いておく**
　　　というのも効果的だ。
　　　でも、最初は公式ドキュメントにアクセスした上で
　　　perlopなりperlsynなり、
　　　特定のカテゴリを参照する癖をつける事をお勧めしておくよ。」

新人「わかりました。」

遣付「ついでに、最初は見る機会が多いであろうPerldocを厳選しておいた。
　　　合わせて参考にしてみてくれ。」

[演算子：perlop(5.26.1)](https://perldoc.jp/docs/perl/5.26.1/perlop.pod)
[文法：perlsyn(5.26.1)](https://perldoc.jp/docs/perl/5.26.1/perlsyn.pod)
[組み込み関数：perlfunc(5.26.1)](https://perldoc.jp/docs/perl/5.26.1/perlfunc.pod)
[特殊変数：perlvar(5.26.1)](https://perldoc.jp/docs/perl/5.26.1/perlvar.pod)
[正規表現：perlre(5.14.1が最新)](https://perldoc.jp/docs/perl/5.14.1/perlre.pod)
[診断メッセージ：perldiag（5.22.1が最新）](https://perldoc.jp/docs/perl/5.22.1/perldiag.pod)　※いわゆる、エラーメッセージ

新人「とりあえず、初手は演算子をベースに記号を知っておく…と。
　　　承知しました！」

###### 第一条 一項：記号で困ったらとりあえずPerldocを見る。

遣付「あ、厳密に記号ではないが最後にもう一つ。
　　　以降のソースコードでは頭に`use strict;`と`use warnings;`が
　　　書かれているものだと思ってくれ。」

```perl:Perlファイル文頭（shebang行を除く）
use strict;
use warnings;
```

新人「お約束事だと思って**何となく**毎度のように書いてはいるんですが
　　　これらは何ですか？」

遣付「`strict`や`warnings`は**プラグマ**と呼ばれる
　　　**Perlコンパイラ**の挙動を変える**モジュール**だ。
　　　**モジュール**というのはよく使われる機能を集めたライブラリのようなもの
　　　だと思ってくれればいい。」

[CPAN モジュール - strict](https://perldoc.jp/docs/modules/strict-1.04/strict.pod)
[CPAN モジュール - warnings](http://perldoc.jp/docs/modules/warnings-1.23/warnings.pod)

新人「あれ？でも**Perlはインタプリタ型言語ではないのですか？**
　　　コンパイラって…」

遣付「そう。Perlは**コンパイラとインタプリタの機能を両方持っている**んだ。」

>
Perl は常にコンパイラを持っています: ソースコードは内部コード (構文木) に 変換され、実行する前に最適化されます。
[perlcompile - Perl コンパイラ・トランスレータの解説](https://perldoc.jp/docs/perl/5.14.1/perlcompile.pod)
>

新人「え？そうなんですか！」

遣付「あぁ。
　　　インタプリタ言語のように動きはするんだけどね。
　　　実際にはPerlスクリプトが実行される前にコンパイルが行われている。」

新人「なるほどー。」

遣付「詳細な説明は省くが、コンパイルが通るという事は
　　　Perlの構文的に問題がない、つまり[構文解析](https://ja.wikipedia.org/wiki/構文解析)が正しく行われ
　　　プログラムが正常に動く状態にある、という事だ。
　　　Perlのプラグマはその構文解析の判定基準を変える。」

新人「ふむふむ。」

遣付「具体的に`strict`プラグマは
　　　変数宣言を強要したり、クォートされていない文字列を禁止したりと
　　　その名（strict）の通り、**文法のチェックを厳しくする**事ができる、
　　　`warnings`プラグマは
　　　例えば、未定義値（undef）を参照しようとしたりした時に
　　　**警告を出力する事ができる**ようになる
　　　というイメージだ。」

新人「書き味というよりは中の動作を揃えるといった感じですね。」

遣付「その通り。
　　　`strict`と`warnings`を使うのは
　　　今の認識の通り**お約束事**だと思って差し支えないと思う。
　　　一般的にも周知の事柄だしね。」

###### 第一条 二項：スクリプトを書く際は`strict`プラグマと`warnings`プラグマを必ず使用する。
`use strict;`
`use warnings;`

新人「わざわざ`use`文まで書いたのには意味がありますか？」

遣付「例えばだけど、PerlのIDEとしてPycharmやIntelliJを導入したとする。
　　　更に、[JetBrainsのPerlプラグインCamelcadeを使ったりする](http://altmo.html.xdomain.jp/src_01/2018_0130/00.html)と
　　　デフォルトの設定だと、新規にPerlファイルを作成した時に
　　　`use strict;`が自動挿入されるのはいいんだけど
　　　`warnings`プラグマは`use warnings FATAL => 'all';`のように
　　　オプションが付いてきてしまう。
　　　これもIDE環境によってはプラグマの宣言が自動生成されたりされなかったりするので
　　　明文化して忘れないようにしておこうというのが目的だね。」

新人「なるほどなるほど。」

遣付「あとはuse文でバージョンを指定したりもできるけど
　　　5.12以降のバージョンをuseすると暗黙的に`strict`プラグマが有効になる
　　　なんてのもある。」

>
バージョン番号 5.11.0 以上を指定した use VERSION 文法を使うと、 (その他の機能が有効化されるのに追加して) ちょうど use strict と同様、レキシカルに strict が有効になります。 以下の表記は:
use 5.12.0;
以下を意味します:
use strict;
use feature ':5.12';
[perl5120delta - perl v5.12.0 での変更点 - 暗黙の strict](http://perldoc.jp/docs/perl/5.12.0/perl5120delta.pod#Implicit32strictures)
>

遣付「`use`文や`プラグマ`に関しては奥が深いのでここでは**深追いしない**が
　　　とりあえず`strict`プラグマと`warnings`プラグマが有効になっていればいい
　　　と思ってくれればいい。」

新人「承知しました！」
　

#### 第二条：演算子にまつわる書き方を統一しよう。

遣付「では早速、演算子の書き方を揃えていこう。
　　　次のコードを見て欲しい。」

```perl:test.pl
my $flg = 0;

if(! $flg){
    print "false";
}
```

新人「えっと、`$flg`が偽なのでfalseが出力されますね。
　　　これが何か？」

遣付「では、これだとどうか？」

```perl:test2.pl
my $flg = 0;

if(!$flg){
    print "false";
}
```

新人「同じですが、論理否定の単項演算子`!`の**後ろにスペースがない**ですね。」

遣付「その通り。
　　　後ろにスペースがあろうがなかろうが
　　　論理否定演算子として作用する。
　　　どちらでも書けるのであれば**できる限りどちらかで書こう**。
　　　細かい事だがこれも標準化の対象だ。」

新人「なるほど。
　　　では、どちらがよいでしょうか？」

遣付「論理否定を示す単項演算子`!`は他の言語、例えばJavaにも存在する。
　　　元々Javaをやっていた人間であれば、
　　　後ろにスペースがない方が馴染みのある分、
　　　読み易いし書きやすいんじゃないかな。
　　　ただ、Perlでは組み込み関数の引数を指定する際も
　　　カッコではなく、スペースで評価させる慣例があるのも事実だ。


```perl:test3.pl
# print関数の一例。
# カッコ付でも動くけど…
print('aaa');
# こちらの方が自然だと思う。
print 'aaa';
```

　　　なので個人的には**スペースで区切った方が自然**だとは思う。
　　　けど、やっぱり最終的には現場の好みかな。

```perl:test4.pl
if(! $flg){
# 中略
```

　　　結論、この第二条の項となるお約束事はこんな風になる。

###### 第二条 一項：論理否定演算子`!`の後にはスペースを一つ置く。

　　　どうかな？」

新人「理解しました。
　　　ただ、ビシッとルールとして書かれると、
　　　何か縛られているようでモヤモヤしますね。」

遣付「書き味がバラバラになるよりはよっぽどマシさ。」

新人「ですね。」

遣付「あとは論理否定つながりで、例えば`not`だな。」

新人「`!`より優先順位が低い論理否定の演算子ですね。
　　　使ったことはありませんが…。」

遣付「よし。じゃあ今回は先に条項を書いてみよう。」

###### 第二条 二項：論理否定演算子`not`は使わない。

新人「え。使わなくていいんですか？」

遣付「うん。**無理に使う必要は全くない**。
　　　むしろ、優先度を履き違えてバグを出すくらいなら**いっそ使わない**、
　　　という選択肢の方が適切だと思う。」

新人「どういう事でしょう？」

遣付「では、否定論理積（NAND）を例に簡単に説明しよう。」

**否定論理積（NAND）**

|A|B|A nand B|
|:---:|:---:|:---:|
|0|0|1|
|0|1|1|
|1|0|1|
|1|1|0|

遣付「否定論理積は命題Aと命題Bが**両方真の場合のみ偽**となる論理式だ。」
　　　また、Perlには**短絡演算（ショートサーキット演算）**という評価方式がある。」

>
二項演算子の "||" は、短絡の論理和演算を行ないます。 つまり、**左被演算子が真であれば、右被演算子は評価さえ行なわれないということです**。
[perlop - Perl の演算子と優先順位 - C スタイルの論理和](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#C-style32Logical32Or) 
>

遣付「これを利用することで、論理演算式はとてもシンプルになる。」

A nand B
= not A || not B

新人「なるほど！
　　　命題Aが偽であれば否定論理積は必ず真という事ですね。
　　　あとは命題Aと命題Bの両方が真であるかを見極めればよい、と。」

遣付「その通り。
　　　では、論理演算を`not`を使って実装してみよう。」

```perl:test5.pl
print "A:B  [A nand B]\n";
print "-------------\n";

for my $meidai_a (0 .. 1) {
    for my $meidai_b (0 .. 1) {
        my $judge = (not $meidai_a || not $meidai_b) ? '1' : '0';
        print "${meidai_a}:${meidai_b}  [${judge}]\n";
    }
}
```

新人「何となく**良さそうに見えます**が…」

遣付「これが実行結果だ。」

```text:実行結果
A:B  [A nand B]
-------------
0:0  [0]
0:1  [1]
1:0  [0]
1:1  [0]
```

新人「全然違うー！」

遣付「これが演算子の優先順位だ。
　　　`not`の優先順位はうんと低い。
　　　上で使われている論理和の演算子`||`よりもっとね。
　　　つまり`not`よりも`||`が先に評価されてしまっているんだ。
　　　実際にはこう動いている。」

```
my $judge = (not ($meidai_a || not $meidai_b)) ? '1' : '0';
```

新人「あ、そうか。`||`の左項を`$meidai_a`だけと見てしまうのか…」

遣付「その通り。ではあらためて`!`で書き直してみよう。」

```Perl:test5_kai.pl
print "A:B  [A nand B]\n";
print "-------------\n";

for my $meidai_a (0 .. 1) {
    for my $meidai_b (0 .. 1) {
        my $judge = (! $meidai_a || ! $meidai_b) ? '1' : '0';
        print "${meidai_a}:${meidai_b}  [${judge}]\n";
    }
}
```

```text:実行結果
A:B  [A nand B]
-------------
0:0  [1]
0:1  [1]
1:0  [1]
1:1  [0]
```

遣付「良さそうだね。」

新人「でも`not`を使わないと実現できないようなロジックはないのでしょうか？」

遣付「ないと思うなぁ。
　　　どの言語でも単項の論理否定演算子`!`はとても優先順位が強いだろう？
　　　もしPerlでの特殊な使いどころがあるのだとしても
　　　潰しが効く/効かないという観点においては
　　　**わざわざ`not`の弱い優先順特性を活かすメリットはあまり感じられない**ね。」

新人「`not`って直感的な単語なのになんか勿体ないですね。」

遣付「そうだね。
　　　強いて使うのであれば単項評価式というのが前提になるけど
　　　`!`の代用として使えなくもない。
　　　でもやっぱりそこまでのメリットはないと思うなぁ。」

```perl:test4_kai.pl
if(not $flg){
# 中略
```

新人「納得しました！」

遣付「あとは基本的な所だと**ハッシュの初期化**かな。
　　　コンマ演算子としてどちらを使うかっていう。」

```perl:test6.pl
my %hash1 = ('a', 1, 'b', 2, 'c', 3);
my %hash2 = (a=>1, b=>2, c=>3);
```

新人「あれ。`%hash2`ではキーをクォートしていませんけどいいんですか？」

遣付「そうなんだ。
　　　`=>`（fat commma）を使う場合は
　　　裸のリテラル（Bareword）が許容される場合があるんだ。

>
=> 演算子(時々「ファットコンマ」と発音されます)はコンマ演算子の 同義語ですが、もし左側の単語が文字か下線で始まっていて、かつ文字、数字、 下線でのみ構成されている場合、これを文字列として扱うという効果もあります。
[perlop - Perl の演算子と優先順位 - コンマ演算子](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Comma32Operator)
>


　　　んで、Perl上**`,`と`=>`は完全に同義**だ。」

新人「へー。じゃあ、ハッシュではファットコンマの方がよさそうですね。」

遣付「そうだね。
　　　一目で『お？ハッシュか？』ってわかるし
　　　いちいちクォートしなくてよい、というのは楽だよね。」

###### 第二条 三項：ハッシュのキー・バリューはファットコンマ（=>）でつなぐ。（初期化時）

遣付「演算子はキリがないのでこの辺にしておこうか。」

新人「はい。深堀りするとしたらどんな方向が望ましいですか？」

遣付「うん。演算子は**優先順位**、そして**評価順（方向）**がとても大切だ。
　　　十三か条の**項**と用語が被ってしまっているけど
　　　Perlには**項（TERM）**という概念が存在する。
　　　とても大事な考え方なのでこれをベースにするとよいね。」

[項とリスト演算子（左方向）](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Terms32and32List32Operators32-40Leftward41)

新人「ふむふむ。」

遣付「あとは面白い演算子も色々あるので
　　　興味があるなら調べてみるといい。
　　　バージョン5.12.1で登場し、5.14.1で名前を変え、
　　　5.16.1でPerldocから**忽然と姿を消した** [ヤダヤダ演算子](https://perldoc.jp/docs/perl/5.12.1/perlop.pod#Yada32Yada32Operator)とか
　　　アルファベットのエックス（`x`）で表現される[繰り返し演算子](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Multiplicative32Operators)とか
　　　デフォルト値を設定可能な[論理定義性和（Defined-or）](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Logical32Defined-Or)とかね。」

新人「へー。なんか面白そうですね。」

遣付「そうなんだ。
　　　面白いのはたくさんあるんだけど全部を無理やり使おうとするのは
　　　**時間的な制約で難しい場合もある**だろう。
　　　それでもメリットが大きいと判断できて、
　　　実用できそうならどんどん標準化していこう。」

新人「はい。わかりました！」

遣付「よし。次にいこう。」
　

#### 第三条：構文糖（糖衣構文）はほどほどに。使うなら統一しよう。

遣付「構文糖は聞いたことあるかな？」

新人「はい。書き味を**省略できる**くらいの認識ですけど。」
　　　
遣付「十分だ。では、さっきの**ハッシュのファットコンマ**を見てみよう。
　　　`%hash1`と`%hash2`に加えて`%hash3`と`%hash4`を追加してみた。」

```perl:test6_kai.pl
my %hash1 = ('a', 1, 'b', 2, 'c', 3);
my %hash2 = (a=>1, b=>2, c=>3);
my %hash3 = ('a'=>1, 'b'=>2, 'c'=>3);
my %hash4 = ("a"=>1, "b"=>2, "c"=>3);
```

新人「あれ。キーのクォートは要らないんじゃ…？」

遣付「そうなんだ。冗長だけど**クォートを記載することもできる**。
　　　この場合、求められる一例としてはこうだね。」

###### 第三条 一項：ハッシュのキーはクォートしない。

新人「そんなケースがあるかはわかりませんが、
　　　**クォートしたい場合はどうしましょう**ね。」

遣付「いい質問だ。
　　　後で**文字列**についての標準化も策定するので
　　　そこで詳しく見ていこう。
　　　じゃあ、次だ。」

```perl:test7.pl
my @arr = ([1, 2, 3], [4, 5, 6], [7, 8, 9]);
my $ref_arr = \@arr;

# リファレンスからアクセス
print $ref_arr->[1]->[2]."\n";
# デリファレンス修飾子からアクセス
print ${$ref_arr}[1]->[2]."\n";
# デリファレンス修飾子のブレースを省略
print $$ref_arr[1]->[2]."\n";

# 別の変数にデリファレンスして代入
my @deref_arr = @{$ref_arr};
print $deref_arr[1]->[2]."\n";
```

新人「えっと…**多次元配列っぽい**、配列の配列ですね。」

遣付「そうだ。
　　　これらの表記を更に省略する事ができる。」

>
矢印は、二つの 添え字 の間にあるのなら、省略できます。
[perlreftut - Mark によるリファレンスに関するとても短いチュートリアル - 矢印のルール](https://perldoc.jp/docs/perl/5.26.1/perlreftut.pod#Arrow32Rule)
>

遣付「つまり、アロー演算子`->`の両側が`()`,`[]`,`{}`の場合は**省略が可能**という事だ。」

```perl:test7_kai.pl
my @arr = ([1, 2, 3], [4, 5, 6], [7, 8, 9]);
my $ref_arr = \@arr;

# リファレンスからアクセス（アロー演算子を一部省略）
print $ref_arr->[1][2]."\n";
# デリファレンス修飾子からアクセス（アロー演算子を省略）
print ${$ref_arr}[1][2]."\n";
# デリファレンス修飾子のブレースを省略（アロー演算子を省略）
print $$ref_arr[1][2]."\n";

# 別の変数にデリファレンスして代入（アロー演算子を省略）
my @deref_arr = @{$ref_arr};
print $deref_arr[1][2]."\n";
```

新人「`$$ref_arr[1][2]`なんかは多次元配列っぽいアクセスで見やすいですし
　　　この表記で書かれているソースも見た事ありますけど
　　　正直これだけ**省略されているというのは意識していなかった**かもしれません。
　　　`$`を頭に重ねて付けておけばいいや、くらいで…。」

遣付「そうだね。
　　　これはまだ配列の配列だからわかりやすいけど、
　　　**配列のハッシュ**とかになると
　　　もしかするとアロー演算子があった方が見やすいのかもしれない。」

```perl:test8.pl
my %hash = (a=>[1, 2, 3], b=>[4, 5, 6], c=>[7, 8, 9]);
my $ref_hash = \%hash;

# 省略なし
print $ref_hash->{b}->[2]."\n";
# 省略あり
print $$ref_hash{b}[2]."\n";
```

新人「うーん。確かに。」

遣付「ネストしたデータ構造下では、
　　　構造そのものの妥当性や建て付けなど
　　　**表記の他にも色々考慮しなくてはいけない**事が多い。
　　　（[perlref - Perlのリファレンスとネストしたデータ構造](https://perldoc.jp/docs/perl/5.26.1/perlref.pod)）
　　　`->`を打つ手間を惜しんだばっかりに可読性が下がって
　　　バグを生み出すリスクが上がってしまうくらいであれば
　　　**慣れない内はデリファレンス修飾子やアロー演算子を省略するべきではない**
　　　と思うけどね。」

###### 第三条 二項：アロー演算子やデリファレンス修飾子は（できるだけ）省略しないで書く。

遣付「これに関しては、例えば配列の配列のように
　　　直感的になる場合も多々ある。
　　　例えば『**ただし配列の配列の場合は中置のアロー演算子は省略する。**』など
　　　例外的なルールは後で追記していけばいい。」

新人「よく見る表記だけを真似して書けばいいってもんじゃない、
　　　という事ですね。了解です！」

遣付「うん。サクサクいこう。」
　

#### 第四条：制御文（条件分岐）はifもしくはunlessとorだけでいい。

遣付「Perlの**条件分岐**という意味での制御文を挙げるとざっとこれだけある。
　　　が、使うのは基本的に`if`と`unless`と`or`だけで十分だ。」

- if
- unless
- or（厳密には文ではなく演算子：[論理和](https://perldoc.jp/docs/perl/perlop.pod#Logical32or32and32Exclusive32Or)）
- ?:（厳密には文ではなく演算子：[条件演算子](https://perldoc.jp/docs/perl/perlop.pod#Conditional32Operator)）
- switch
- given
- goto

新人「**gotoがまずい**ってのは何となくわかりますが、
　　　その他はなんででしょうか？」

遣付「その前に、Perlの**真偽値**について説明しておこう。
　　　Perlでは先に**偽の定義があって、偽でないものを真とする**んだ。」


>
数値 0, 文字列 '0' と '', 空リスト (), undef は全て真偽値 コンテキストでは偽となります。 その他の全ての値は真です。
[perlsyn - Perl の文法 - 真偽値](https://perldoc.jp/docs/perl/5.8.8/perlsyn.pod#Truth32and32Falsehood)
>

新人「あの、真偽値コンテキストって何ですか？」

遣付「スカラコンテキストの一種だと思ってくれていい。
　　　スカラの中身が文字列なら文字列コンテキスト、
　　　数値なら数値コンテキスト、みたいな。
　　　つまり条件式でのコンテキストだな。」

新人「あぁ、つまりはif文の中って事ですね。」

遣付「そういう事だ。
　　　じゃあ上から見ていこう。
　　　`if`と`unless`は簡単に言うと
　　　『**偽でない場合**』と『**偽である場合**』の評価をする制御文だ。」

```perl:test9.pl
my $flg = 0;

if($flg){
    print "sin\n";
}

unless($flg){
    print "gi\n";
}
```

```text:出力結果
gi
```

遣付「数値の0はPerlでは偽となる。
　　　つまり`$flg`は真偽値コンテキストでは『偽』だ。
　　　上の`if`文は`$flg`が偽なので実行されないが
　　　`unless`文は`$flg`が偽なので実行される、という事だね。」

新人「`if`に否定演算子の`!`を使ったらダメですか？」

```perl:test9_kai.pl
my $flg = 0;

if($flg){
    print "sin\n";
}

if(! $flg){
    print "gi\n";
}
```

遣付「この場合ならそれでもいいかもね。
　　　でもPerlには**[文修飾子](https://perldoc.jp/docs/perl/5.26.1/perlsyn.pod#Statement32Modifiers)**という文法があってこんな風にもかけるんだ。
　　　後置のif、後置のunlessなんて呼び方もするね。」

```perl:test9_kai_kai.pl
my $flg = 0;

print "sin\n" if $flg;
print "gi\n" unless $flg;
print "gi\n" if ! $flg;
# ブロックをつける事もできるけど…
print "gi\n" if(! $flg);
```

新人「おー。すっきりした。」

遣付「これだとどうだい？
　　　ブロックのカッコがないのもそうだけど
　　　**unlessの方が読み易く**はないか？」

新人「確かに…」

遣付「偽である事を明確に判定したいというケースも中には存在するはずだ。
　　　特にPerlはTrue/Falseみたいな真偽の二値をもっているわけではなく
　　　**偽の定義ありきで、偽でないものが真**だからね。」

```perl:test10.pl
my $var1;

# var1がundefなら'aiueo'を代入。
$var1 = 'aiueo' unless defined $var1;
# ↓よりみやすくない？
# $var1 = 'aiueo' if ! defined $var1;
# ちなみに「defined-or」を使うと↓のように書ける。
# $var1 //= 'aiueo';

print $var1;
```

新人「なるほどなるほど。」

遣付「文修飾子の話が出たので、ついでに話しておくと
　　　**文修飾子は変数宣言時は使わない**ようにしよう。」

>
注意: (my $x if ... のような) 条件構造やループ構造で修飾された my state,our 文の振る舞いは 未定義 です。 my 変数の値は undef かも知れませんし、以前に代入された値かも 知れませんし、その他の如何なる値の可能性もあります。 **この値に依存してはいけません。**
[perlsyn - Perl の文法 - 文修飾子](https://perldoc.jp/docs/perl/5.26.1/perlsyn.pod#Statement32Modifiers)
>

```perl:test11.pl
# これならいいが…
my $var1;
my $var2 = 'aiueo' unless defined $var1;
print $var2."\n";
# 出力「aiueoと改行」

# これだとvar4がundefなのでprint $var4でエラーとなる。
my $var3 = 'kakikukeko';
my $var4 = 'sasisuseso' unless defined $var3;
print $var4."\n";
# 出力「Use of uninitialized value $var4 in concatenation (.)」
# undefと改行を結合しようとして怒られている。
# 例え、print $var4;にしたとしても
# 「Use of uninitialized value $var4 in print」が出て怒られる。
# 要はundefのものを使うんじゃねぇという事だね。
```

新人「Perlが真偽値のベースとして偽を扱う事は理解しました。
　　　でも、**条件分岐がネストする時はifの方が良い**のではないでしょうか？」

遣付「素晴らしい。その通りだ。
　　　`elsif`はあるけど**`elsunless`はない**からね。
　　　だから**`unless`は文修飾子にしか使わない**というルールにした方がよいかもだ。」

```Perl:test12.pl
# これならいい。
unless($flg == 0){
    #（中略）
}

# これもまだいい。
$hoge = 'aiueo' unless defined $flg;

# ただ、こうなっちゃうと…わかりずらい。
unless($flg){
    #（中略）
}else{
    #（中略）
}

# 素直にifで書いた方がよい。
if(! $flg){
    #（中略）
}else{
    #（中略）
}

# 何なら条件分岐も増やせるしね。
if(! $flg){
    #（中略）
}elsif($flg == 1){
    #（中略）
}elsif($flg == 2){
    #（中略）
}else{
    #（中略）
}
```

新人「承知しました！
　　　先走ってしまうと、こんな感じでしょうか？」

###### 第四条 一項：条件分岐には基本的にif文を使用する。
###### 第四条 二項：unless文は文修飾子でのみ使用する。

遣付「いいね！いい感じだ。
　　　話が若干逸れたが、**`if`と`unless`はよく使う**という所で
　　　次の`or`にいこう。」

```perl:test13.pl
my $file = "C:\\data\\read_only.txt";
# 特殊変数「$!」はシステムコールエラー。
open(my $fh, "<", $file) or die "Can't open $file:$!";

while(my $line = <$fh>){
    print $line;
}
```

遣付「ファイルオープンする時には`open`と`or`がよくセットで使われる。
　　　何なら**ファイルオープンのイディオムと言ってもいい**かもしれない。」

新人「ファイルが開けなかったら`die`でプログラム終了という事ですね。
　　　でも`or`ってそもそもどういう演算子なのでしょうか？」

遣付「前に出てきた`not`と同じで、優先順位がとても低い演算子なんだ。
　　　しかも`not`より低く、演算子の中でも最低の部類だ。
　　　こうして`or`の左項の式評価が偽の場合、
　　　右項が実行（評価）されるという塩梅になる。」

新人「なるほどー。」

遣付「逆に、このイディオムの他で使うかと言うと
　　　**すぐには出てこない**ので、とりあえずこれだけ書いておこう。」

###### 第四条 三項：or文はファイルのopenイディオムでのみ使用する。

遣付「次は**条件演算子**か。他の言語では**[三項演算子](https://ja.wikipedia.org/wiki/%E6%9D%A1%E4%BB%B6%E6%BC%94%E7%AE%97%E5%AD%90#%E4%B8%89%E9%A0%85%E6%BC%94%E7%AE%97%E5%AD%90)**なんて呼ばれていたりもするね。」

```perl:test14.pl
# 普通の条件演算子
my $input1 = 0;
my $output1 = $input1 ? 1 : 3;
print $output1;
print "\n";

# 条件演算子のネスト
my $input2 = 2;
my $output2 = $input2 == 1 ? 2 : $input2 == 2 ? 3 : 4;
print $output2;
```

新人「えっと…えっと…出力はどちらも3ですね。」

遣付「そう。条件演算子はこのようにネストもできるんだけど
　　　ちょっと**見づらい**よね。
　　　これならif文で書いた方がよっぽど見やすい。」

```perl:test14_kai.pl
my $input = 2;
if($input == 1){
    $output = 2;
}elsif($input == 2){
    $output = 3;
}else{
    $output = 4;
}
print $output;
```

新人「場合によりけり、ですかね？」

遣付「そうだね。
　　　真偽値判定だけで単純な条件演算子ならよいかもだけど
　　　複雑なのはあまりよくないと思う。」

新人「わかりました！こうですね？」

###### 第四条 四項：条件演算子（三項演算子）はもし使うならシンプルに。

遣付「うん…曖昧過ぎる気もするが、まぁいいか。」

新人「はい！楽しくなってきました！」

遣付「いいぞ。じゃあ、条件分岐はこの辺でいいか。」

新人「はい！って、あの`switch`と`given`と`goto`は…？」

遣付「**使わない**。以上だ。」

新人「えぇ…」

遣付「じゃあ、触りだけ。
　　　`switch`はモジュールで、`given`は構文なのでモノとしては別の物だが
　　　どちらもいわゆる[Switch文](https://ja.wikipedia.org/wiki/Switch%E6%96%87)だ。
　　　『perl switch given 性能』でググればわんさか出てくるのでわかるが
　　　とにかくifより**遅い**んだ。
　　　使う必要はない。
　　　とりあえずPerldocを引用してツッコミを入れておこう。」

>
このいかすコードのどこかに間違いなく重大なバグが潜んでいる**（笑）** バグレポートやフィードバックは大歓迎。
[Switch - Perlのswitch文](https://perldoc.jp/docs/modules/Switch-2.09/Switch.pod)
>

⇒何わろとんねん。

>
given と when の実験的な詳細
既に述べたように、"switch" 機能は非常に実験的であると考えられています; ほとんど知らせることなく変更されることがあります。 特に when は**トリッキー**な振る舞いがあり、将来より**トリッキー**で なくなるように変更される予定です。 現在の(誤)実装に依存しないでください。 Perl 5.18 より前では、given には、コードが古いバージョンの Perl でも 動かなければならない場合に気をつけるべき**トリッキー**な振る舞いもあります:
[perlsyn - Perl の文法 - given と when の実験的な詳細](https://perldoc.jp/docs/perl/5.22.1/perlsyn.pod#Experimental32Details32on32given32and32when)
>

⇒何回トリッキー言うねん。

遣付「gotoはそうだな…[構造化プログラミング](https://ja.wikipedia.org/wiki/%E6%A7%8B%E9%80%A0%E5%8C%96%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)と[goto文](https://ja.wikipedia.org/wiki/Goto%E6%96%87)の
　　　Wikipediaでも読んでおけばいいだろう。」

新人「あっさりですね…」

遣付「あぁ、あまり関わりたくないからな…」
　

#### 第五条：制御文（ループ）はforかwhileでいい。

遣付「さぁ、次はループ文だ。ざっとこれだけある。」

**ループ文**
- for
- foreach
- while
- until
- do while（厳密には文ではなく[doブロック](https://perldoc.jp/func/do)に対して文修飾子whileを付けたもの）
- while eachイディオム

**ループ制御文**
- last
- next
- redo（厳密には文ではなく[redo関数](https://perldoc.jp/func/redo)）
- continue（ブロックありきで実行制御文扱い）

遣付「ループは絶対に触るものだし**サラッ**といこう。
　　　まず、`for`と`foreach`は**等価**だ。
　　　Perldocに明記されるようになったのは5.16.1からっぽいけど
　　　5.10.1でも同様に動くので、まぁそういう事なんだろう。」

>
foreach は実際には for の同義語なので、どちらでも使えます。
[perlsyn - Perl の文法 - foreachループ（5.16.1）](https://perldoc.jp/docs/perl/5.16.1/perlsyn.pod#Foreach32Loops)
>

遣付「事実、以下のコードは１～３までの数字をprintするコードだが
　　　全て`for`でも`foreach`でも書ける。」

```perl:test15.pl
# foreachに変えても同じ
for(my $i=1; $i<4; $i++){
    print $i;
}

# foreachに変えても同じ
for my $j (1, 2, 3){
    print $j;
}

# foreachに変えても同じ
my @arr = (1, 2, 3);
for my $k (@arr){
    print $k;
}

# foreachに変えても同じ
for my $h (1 .. 3){
    print $h;
}

# foreachに変えても同じ
for (1 .. 3){
    print $_;
}
```

新人「Perldocにはこんな記述があるのですが
　　　`foreach`との使い分けは不要でしょうか？」

>
変数の前に**my**というキーワードが置かれていた場合、**その変数はレキシカルスコープを持ち、したがってそれはループの中でのみ可視となります。** このキーワードがなければ、変数はループに対してローカルとなり、ループを 抜けた後で以前の値が再度取得されます。 変数が事前に my を使って宣言されていたならば、グローバルなものの 代わりにその変数を使いますが、それもループにローカルなものとなります。 この暗黙のローカル化は **foreachの中でのみ** 起きます。
[perlsyn - Perl の文法 - foreachループ](https://perldoc.jp/docs/perl/5.26.1/perlsyn.pod#Foreach32Loops)
>

遣付「うん。**等価**の方が強い。
　　　要は`for VAR (LIST)`で書いたら、という事だね。
　　　`VAR`が`my`付きならそれはループ内でのレキシカル変数という事になる。」

新人「はぁ、本当に**同じ**なんですね。」

遣付「そうなんだ。
　　　人によっては慣習的に**配列は`foreach`で回したい**という人もいるかもだけど
　　　とりあえず`for`に統一しよう。」

###### 第五条 一項：foreachは使わない。

遣付「それとこうだ。」

###### 第五条 二項：for文のVARは省略しないで必ずmyをつける。

新人「これは…？」

遣付「test15.plでは`for`と`foreach`が同じ事を示すために
　　　あえて`VAR`を省略して書いてみたけど、
　　　`VAR`を省略すると`$_`で受けなくてはいけない。
　　　これは可読性が良いとは言えないね。」

```perl:test15_kai.pl
# $_はやめよう？
for (1 .. 3){
    print $_;
}

# 面倒くさくてもレキシカルスコープを持つ変数をmyで宣言して運用しよう。
for my $i (1 .. 3){
    print $i;
}
```

新人「では`my`をつけない形はどうですか？」

```test16.pl
my $i;
for $i (1 .. 3){
    print $i;
}
```

遣付「この記述だね。

>
このキーワード(`my`)がなければ、変数はループに対してローカルとなり、ループを 抜けた後で以前の値が再度取得されます。
[perlsyn - Perl の文法 - foreachループ](https://perldoc.jp/docs/perl/5.26.1/perlsyn.pod#Foreach32Loops)
>

　　　うーん。
　　　それでも動くんだけど余程の事情がない限り**ナシ**だねぇ。
　　　**初期化していないように見えるのに、普通に動くのが気持ち悪い**し
　　　明示的に初期化したとしても、途中で値が変わるっていうか
　　　二重の用途で変数を運用しているように見えるし。」

```perl:test16_kai.pl
my $i;
for $i (1 .. 3){
    # 1～3を出力
    print $i;
}
# ↓はエラーになる
# （初期化されていないから）
# （for文によって代入された1～3の値のライフサイクルはfor文の中でだけ有効）
#print $i;

# じゃあ初期化してみよう。
my $j = 0;
for $j (1 .. 3){
    # 1～3を出力
    print $j;
}
# 0を出力。（不自然じゃない？）
print $j;
```

新人「なるほど。理解しました。」

遣付「よし。じゃあ`while`だ。
　　　`while`はファイルをオープンするコードでも見たね。」

```perl:test13.pl
my $file = "C:\\data\\read_only.txt";
# 特殊変数「$!」はシステムコールエラー。
open(my $fh, "<", $file) or die "Can't open $file:$!";

while(my $line = <$fh>){
    print $line;
}
```

遣付「`for`と違って`while`はループ条件だけで動く。
　　　`while(EXPR)`で`EXPR`が**真**なら動き続けるという形だ。
　　　シンプルだからこそ**意図せぬ無限ループ**には気を付けないといけない。」

新人「ふむふむ。」

遣付「上のファイルオープンのように**ループ対象が有限**であればよいが
　　　**無限**のものを扱う場合は**ループを抜ける設計が必須**となる。
　　　ループ制御については後で説明しよう。」

新人「わかりました。」

遣付「`while`と似たような制御で`until`がある。
　　　これは`until(EXPR)`で`EXPR`が**偽**なら動き続けるという形だ。
　　　`if`に対する`unless`みたいなもんだね。
　　　ただ`while`と`for`で代用できるから**無理に使う必要はない**。」

新人「`for`と`while`だけの方がまぁシンプルだと思います。」

遣付「えっと、次は`do while`と`while eachイディオム`だね。**使わない**。」

新人「また！？思いの外、説明がサラッといかなくて
　　　**ちょっと飽きていませんか**？」

遣付「まさか、そんな事はないよ…しょうがない。
　　　じゃあ簡単に説明しよう。
　　　`until`と同様に`for`と`while`で代用が効く
　　　というのも使わない理由としては大きいけど
　　　`do while`はループのような動作はするが、厳密には**ループ文ではない**。
　　　`doブロック文`に文修飾子の`while修飾子`を付けただけだ。
　　　だから**ループ制御文も効かない**。論外。

>
do BLOCK はループとしては 扱われません; 従って、next, last,redo といったループ制御文は ブロックから抜けたり再開することはできません。
[perlfunc - do](https://perldoc.jp/func/do)
>

　　　はい。あと`while eachイディオム`ね。
　　　主に`while`と組み合わせてイテレータとして使うとわかりやすい。

```perl:test17.pl
while(my ($k, $v) = each(%hash)){
    print "key=$k, value=$v¥n";
}
```

　　　`each`は関数だね。

>
ハッシュに対してリストコンテキストで呼び出した場合は、次の要素に対する、 ハッシュのキーと値を返します。 **Perl5.12以降でのみ、配列のインデックスと値からなる 2 要素のリストを返す**ので、反復を行えます; より古い Perl ではこれは 文法エラーと考えられます。 スカラコンテキストで呼び出した場合は、 ハッシュの場合は(値ではなく)キー、配列の場合はインデックスを返します。
[perlfunc - each](https://perldoc.jp/func/each)
>

　　　元々はハッシュの為の関数だったけど、5.12以降は**配列でも使える**んだ。
　　　どちらかというと配列で使いたかったのに
　　　この現場は**5.10.1**だから…（震え声）」

```perl:test17_kai.pl
# Perl5.12以降でのみ使用可能
while(my($i, $v) = (@arr)){
    print "index=$i, value=$v¥n";
}
```


新人「自分が使えないからって、すねないでください。」

遣付「冗談はさておき
　　　Perl言語に慣れるまでは
　　　**普通の`for`と普通の`while`で十分**というのが伝えたかった事だ。
　　　ただ`while eachイディオム`は本当に便利なので
　　　後でちゃんと標準化してもいいかもね。」

###### 第五条 三項：untilは使わない。
###### 第五条 四項：do whileは使わない。
###### 第五条 五項：while eachイディオムは使わない。（改訂の余地あり）

新人「わかりました！」

遣付「じゃあ、ループ制御文にいこう。」

```perl:test18.pl
my @arr = (1, 2, 3, 4, 5);

for my $v (@arr){
    if($v == 1){
        next;
    }
    print $v;
    if($v == 4){
        last;
    }
}
# 234を出力して終了
```

遣付「このように
　　　**ループを抜ける際は`last`**
　　　**ループを次の周に移すには`next`**を使う。
　　　`while`で話した無限ループの終了条件についても話そう。
　　　無限ループを前提として建て付けた次のコードを見てほしい。」

```perl:test19.pl
my @arr = ();
my $str = 'A';
# 無限ループ
while(1){
    # @arrの最後のインデックスが4になったらループを抜ける。
    if($#arr == 4){
        last;
    }
    # @arrに対してインデックスを増やしながら要素を追加していく。
    push @arr, $str++;
}
print @arr;
# ABCDEを出力して終了
```

新人「サラッと書かれてますけど、`push`し忘れたら無限ループですね。」

遣付「そう。だから無限ループ前提でループを回す際は
　　　**『lastをコールしているか？』**だけでなく
　　　**『lastがコールされる条件が確実に収束するか？』**という確認が超重要だ。
　　　だから無限ループを使わなくてよいのであれば、**無理に使うのはやめよう**。
　　　上みたいにイキって書かなくても、次のように`for`で十分だ。」

```perl:test19_kai.pl
my @arr = ();
my $str = 'A';
for(my $i=0; $i<5; $i++){
    push @arr, $str++;
}
print @arr;
# ABCDEを出力して終了
```

新人「面白味はないですが確実なのが一番ですね。」

遣付「その通り。じゃあ、ループ制御文はこれで…」

新人「**待った！**
　　　`redo`と`continue`を使わないのは何となく察しましたから
　　　せめて使わない理由を！」

遣付「…わかったよ。
　　　`redo`は、`next`のように次の周に移るのではなく
　　　**現在の周をやり直す**んだ。

>
redo コマンドは、条件を再評価しないで、ループブロックの 始めからもう一度実行を開始します。 
[perlfunc - redo](https://perldoc.jp/func/redo)
>

　　　動きとしては`goto`だよね。だから**使わない**。

　　　で、Perlの`continue`は一般的な[continue文](https://ja.wikipedia.org/wiki/Continue%E6%96%87)と違って
　　　コマンド文ではなく、**ブロックを伴う実行制御文**として動作する。

>
BLOCK が引き続く場合、continue は実際には関数ではなく、 実行制御文です。 continue BLOCK が BLOCK (典型的には while または foreach の中)にあると、これは条件文が再評価される直前に常に実行されます; これは **Cにおけるforループの3番目の部分と同様**です。
[perlfunc - continue](https://perldoc.jp/func/continue)
>

```perl:continue
    while (EXPR) {
        ### redo always comes here
        do_something;
    } continue {
        ### next always comes here
        do_something_else;
        # then back the top to re-check EXPR
    }
    ### last always comes here
```

　　　Perldocの説明にある通り
　　　ループ条件の**評価前**に実行する動作を記述するのが`continueブロック`だ。
　　　**ブロックで定義しないといけないほど評価前の処理を書かなくてはいけない**
　　　という状況がそもそもループロジックの建て付けとしておかしい気がするよね。
　　　だから**使わない**。」

新人「そんなに、まくしたてなくても…」

遣付「面倒くさくはなっていないぞ。**本当だぞ。**
　　　よし。まとめだ。」

###### 第五条 六項：ループを実現する際はfor文かwhile文を使用する。（冗長記載だけど明記しておく）
###### 第五条 七項：無限ループを実装する場合は、ループ終了条件が収束するように確実に設計する。（具体策は別途、考えよう）
###### 第五条 八項：ループ制御文はnextとlastのみを使用し、redoとcontinueは使わない。

新人「ループは`for`と`while`だけ…
　　　ループ制御は`next`と`last`だけ
　　　…うん！シンプルですね。」

遣付「よかった。次にいこう。」
　

#### 第六条：文字列の取り扱いを決めよう。

遣付「まず**文字列とは？**からいこうか。」

>
文字列リテラルは、シングルクォートかダブルクォートで区切られます。 これらは、標準 Unix シェルのクォートと同じように扱われます: ダブルクォートの文字列リテラルでは、**バックスラッシュの置換と 変数の置換が行なわれ、**シングルクォートの文字列では、 (\' と \\を除いて)これらの置換は行なわれません。
[perldata - Perl のデータ型 - スカラ値のコンストラクタ](https://perldoc.jp/docs/perl/5.26.1/perldata.pod#Scalar32value32constructors)
>

遣付「`'`もしくは`"`で括られたモノが文字列という事だね。
　　　で、`"`の場合は**変数の置換が行われる**とある。
　　　つまりこういう事だ。」

```perl:test20.pl
my $whatis = 'pen';
print "This is a $whatis";
```

遣付「この`"`の中で変数が置換される事を**[文字列補間](https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E5%88%97%E8%A3%9C%E9%96%93)**と呼ぶ。」

新人「**変数展開**ではないんですか？」

遣付「**変数展開でも合っている**よ。
　　　文字列補間の方がより広義な呼称だね。
　　　ただ、**変数展開の方が言葉の響き的にしっくり来る**し、
　　　一般的に受け入れられているみたいだから
　　　ここでの**呼び方は変数展開にしよう**か。」

新人「了解です。」

遣付「で、連続した文字列の中で変数展開する際は`${}`を使う。」


>
いくつかのシェルと同じように、**変数名の前後に中かっこを入れて、つながっている英数字(および下線)から切り離せます。** 変数を文字列に展開する時に、後に続くコロン 2 つやシングルクォートと 変数名を分割する場合にもそうしなければなりません; さもなければパッケージのセパレータとして扱われるからです:
[perldata - Perl のデータ型 - スカラ値のコンストラクタ](https://perldoc.jp/docs/perl/5.26.1/perldata.pod#Scalar32value32constructors)
>

```perl:enclose
    $who = "Larry";
    print PASSWD "${who}::0:0:Superuser:/:/bin/perl\n";
    print "We use ${who}speak when ${who}'s here.\n";
```

遣付「つまり**変数名の後に続く文字列と切り離したい**時だね。」

```perl:test21.pl
# 「FooBarBaz」と連続した文字列を出力したい
my $foo = 'Foo';
my $baz = 'Baz';

# ↓はエラーとなる。$fooBarまでを変数として展開しようとするから。
# print "$fooBar$baz";

# これならOK。
print "${foo}Bar$baz";

# bazは冗長でも、「${}」で揃えた方がまだ見やすい。
print "${foo}Bar${baz}";
```

新人「へぇ。**ブレース`{}`の中に記号は要らない**んですね。」

遣付「シェルで慣れていない人にとっては**ん？**って思うかもしれないね。
　　　まぁ慣れだ。」

新人「了解です！」

遣付「じゃあ**第三条**の振り返りをしようじゃないか。」

>
第三条 一項：ハッシュのキーはクォートしない。
新人「そんなケースがあるかはわかりませんが、
　　　**クォートしたい場合はどうしましょう**ね。」
>

```perl:test6_kai.pl
my %hash1 = ('a', 1, 'b', 2, 'c', 3);
my %hash2 = (a=>1, b=>2, c=>3);
my %hash3 = ('a'=>1, 'b'=>2, 'c'=>3);
my %hash4 = ("a"=>1, "b"=>2, "c"=>3);
```

遣付「これだね。」

新人「そうでした。
　　　という事は、`%hash4`のハッシュキーは変数展開できるという事でしょうか？」

```perl:test6_kai_kai.pl
my $key_a = 'a';
my %hash4 = ("$key_a"=>1, "b"=>2, "c"=>3);
# もしくは冗長だけどこう。
my %hash5 = ("${key_a}"=>1, "b"=>2, "c"=>3);
```

遣付「その通り。」

新人「うーん。
　　　**動的にハッシュキーを設定する**というケースも
　　　絶対にないとは言い切れないですよね。
　　　でも、**ハッシュキーをクォートしない**というルールに抵触してしまう…」

遣付「じゃあ、早速だけど、**第三条一項を微調整して改訂**しよう。」

新人「いきなりですか？」

遣付「なに、大した事じゃない。**曖昧だった部分を補強するだけ**さ。
　　　よく見てほしい。
　　　最初に決めた時に扱ったコードも、今見ているコードも
　　　**ハッシュの初期化子**だよね？」

新人「あ。確かに。」

遣付「という事はだ。
　　　**空ハッシュとして初期化しておいて値を詰める**形でも
　　　大筋の初期化という意味では同じだよね。」

```perl:test22.pl
# 初期化子を使って初期化
my %hash1 = (a=>1, b=>2, c=>3);

# 空ハッシュで初期化
my %hash2 = ();
$hash1{a} = 1;
$hash1{b} = 2;
$hash1{c} = 3;
```

新人「…！という事は…
　　　これでどうですか！？」

###### 第三条 一項（改訂）：ハッシュの初期化子において、キーはクォートしない。

遣付「うん。いいと思う。
　　　ハッシュの動的キーについてはどうする？」

新人「初期化子でやらないとなると…
　　　**2通り**のやり方が出てきてしまうんですが
　　　どっちが良いでしょうか？」

```perl:test23.pl
# 「XXXXBarXXXX」というハッシュキーを設定したい。
# 「XXXX」は動的な文字列。

my %hash = ();
my $prefix = 'Foo';
my $suffix = 'Baz';

# とりあえず「FooBarBaz」というキーを設定しよう。（値は1）

# やり方A: 文字列連結演算子
$hash{$prefix.'Bar'.$suffix} = 1;

# やり方B: 変数展開
$hash{"${prefix}Bar${suffix}"} = 1;
```

遣付「あくまで個人的な考え方だけど、
　　　**文字列のみの連結であれば変数展開が望ましい**と思うね。
　　　何故なら、**関数を挟む場合には文字列連結演算子`.`の方が見やすい**からだ。

```perl:test24.pl
# 「HEADXXXX_XXXX_XXXX」というハッシュキーを設定したい。
# 「XXXX」は動的な文字列。

# 結合対象のデータ（プレフィックスと配列）
my $prefix = 'HEAD';
my @arr = ('Foo', 'Bar', 'Baz');

# $keyに「HEADFoo_Bar_Baz」を設定。
my $key = $prefix . join('_', @arr);
# ハッシュキーをセット
$hash{$key} = 1;
```

新人「なるほど！
　　　加えて、キーが長くなる場合は、変数は一つ増えますけど
　　　**キーに文字列を直接的に設定しない**方が見やすいは見やすいですね。」

遣付「さぁ、まとめて最後までやっちゃおう。
　　　**文字列の標準化**はどうなる？
　　　**ハッシュキーのクォート**とも整合性が合うか確認してみよう。」

新人「わかりました！
　　　これがこうなって…これで如何ですか！？」

###### 第三条 一項（改訂）：ハッシュの初期化子において、キーはクォートしない。キーを動的にしたい場合はハッシュを初期化したあとに行う。
###### 第六条 一項：文字列変数のみを引用する場合は変数展開`${}`を使用する。
###### 第六条 二項：文字列変数に加えて関数を引用する場合は変数展開と合わせて、文字列連結演算子`.`を使用する。
###### 第六条 三項：変数展開を行う際に、見通しがよくなるのであれば冗長であっても`${}`を使う。
###### 第六条 四項：ハッシュの代入において、キー値に変数展開を用いてもよいが、見づらくなるようであれば、キー値用のスカラ変数を別途用意する。

遣付「お見事！」

新人「えへへ。」

遣付「じゃあ、**クォート風演算子**についてもついでに説明しておこう。
　　　Perlはクォート文字だけではなく
　　　**クォート風演算子**という別の汎用的な記法を持っている。

>
クォートはリテラル値であると考えるのが普通ですが、Perl において、 クォートは演算子として働き、さまざまな展開やパターンマッチの機能を 持っています。 そのような動作をさせるのに、Perl は慣習的にクォート文字を使っていますが、 **どの種類のクォートも、自分でクォート文字を選べるようになっています。** 以下の表では、{} がその選んだ区切文字のペアを示しています。
[perlop - Perl の演算子と優先順位 - クォートとクォート風の演算子](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Quote32and32Quote-
like32Operators)
>

|通常記法|一般的な呼称|汎用記法|
|:--:|:--:|:--:|
|''|シングルクォーテーション|q{}|
|""|ダブルクォーテーション|qq{}|
※抜粋

遣付「つまり、`''`と`""`のリテラルはそれぞれ次のようにも書ける。」

```perl:test25.pl
my $str1 = 'aiueo';
my $str2 = q{aiueo};

print "Equal\n" if ($str1 eq $str2);
# Equalを出力

my $ve = 'Bar';
my $str3 = "Foo${ve}Baz";
my $str4 = qq{Foo${ve}Baz};

print "Equal\n" if ($str3 eq $str4);
# Equalを出力

# 実は区切り文字はブレースでなくてもいい。
my $str5 =q(aiueo);
my $str6 =q/aiueo/;
my $str7 =q#aiueo#;
my $str8 =q!aiueo!;
my $str9 =q[aiueo];

my $str10 =qq(Foo${ve}Baz);
my $str11 =qq/Foo${ve}Baz/;
my $str12 =qq#Foo${ve}Baz#;
my $str13 =qq!Foo${ve}Baz!;
my $str14 =qq[Foo${ve}Baz];
```

遣付「中でも特殊なのは**単語リスト演算子`qw{}`**だな。
　　　これは**`''`リテラルを要素とするカンマ区切りの文字列リスト**を表現する。
　　　配列の初期化においては、
　　　カッコやらシングルクォーテーションやら
　　　カンマやらを省略できる、というのが強みではあるのだが…」

```perl:test26.pl
# 以下は全て同じ配列
my @arr1 = ('Aa', 'Bb', 'Cc', 'Dd');
my @arr2 = qw(Aa Bb Cc Dd);

# 区切り文字にはカッコ以外も使用可能。
my @arr3 = qw/Aa Bb Cc Dd/;
my @arr4 = qw{Aa Bb Cc Dd};
my @arr5 = qw#Aa Bb Cc Dd#;
my @arr6 = qw!Aa Bb Cc Dd!;
my @arr7 = qw[Aa Bb Cc Dd];
```

新人「うーん、何か**区切り文字が何でもいい**って所が気になりますね…」

遣付「そうなんだ。
　　　配列だけでなく**単純リテラルの文字列リストを扱う場面**においては
　　　強いことは明らかなんだけど、
　　　使うならもっと細かく条件付けして
　　　明示的に標準化した方がよい気がするね。」

新人「…先送りにしますか。」

遣付「…そうだね。」

###### 第六条 五項：クォート風演算子は使わない。（暫定）

遣付「もし**正規表現**を触る事が増えてきたら
　　　振り返りの意味もこめてクォート風演算子をきっちり標準化しよう。
　　　あと、**ヒアドキュメント**なんかも使いようによっては強力だ。
　　　クォート風演算子のそれぞれの細かい挙動については
　　　Perldocに載っているから興味があったら見ておいてくれ。」

[perlop - Perl の演算子と優先順位 - クォート風演算子](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Quote-Like32Operators)

新人「わかりました！」
　

#### 第七条：変数名は確実に命名しよう。

遣付「基本中の基本だな。
　　　大筋としてPerlに限った内容ではないけど書いておこう。」

新人「命名は気にしているつもりですが…
　　　あ！この**[記事](https://qiita.com/jeyei/items/2c385e4e0488a5fa2591#%E5%A4%89%E6%95%B0%E3%81%AE%E8%B6%85%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%A6%82%E5%BF%B5)**がとても参考になりました！」

遣付「どれどれ…うん、**説明を続けよう**。」

新人「（無視された…）」

遣付「『変数』で一番大事な概念は何より**『名実一体』**であることだ。」

新人「（書いてること、同じじゃん！）」

遣付「何の用途で、中にどんな値が入ってて、
　　　そしてどのように扱い、適用し、加工し
　　　変数としての役割をどう全うするのか、
　　　つまり、**スコープ**や**ライフサイクル**だな、
　　　そこらへんを踏まえて、**この変数は何者か？**というのが
　　　できる限り一目で認知されるよう命名をすべきだ。」

新人「な、なるほど。わかります。」

遣付「まぁ`$tmp`とか曖昧な変数を広いスコープで気軽に使うな、とか
　　　[ハンガリアン記法](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%B3%E3%82%AC%E3%83%AA%E3%82%A2%E3%83%B3%E8%A8%98%E6%B3%95)はやめろ、とか
　　　汎用的に細かい事を言い出すとキリがないので
　　　Perlに特化した**超基本を２つだけ**決めておこう。」

新人「変数の標準化って何か大事な位置づけっぽいですけど…
　　　**２つだけ**ですか？」

遣付「最初はそれでいい。
　　　後で必要に応じて適宜追加していこうじゃないか。」

新人「了解です。」

遣付「まず一つ目。」

###### 第七条 一項：同じ変数名を使わない。

新人「？？？どういうことですか？」

遣付「これを見てくれ。」

```perl:test27.pl
my $tmp = 1;
my @tmp = (2,3,4);

# 1を出力
print $tmp;
# 234を出力
print @tmp;
# 2を出力
print $tmp[0];
```

新人「えぇぇぇぇ！！**Sigilが違うと別の変数**なんですか？」

遣付「そうだ。**怖い**だろう？」

新人「おっかねぇ…知りませんでした。」

遣付「なのでどんなに小さいスコープであっても
　　　**同名か同名でないかは確認するべき**だ。
　　　思わぬ事故に繋がりかねない。」

新人「気を付けます。」

遣付「じゃあ二つ目。」

###### 第七条 二項：一文字の変数は使わない。

新人「…説明を貰えますか？」

遣付「君が１か月前に書いたサンプルコードを見てみよう。」

```sinjin2.pl
my $a = 0;
my $b = 1;
# 01を出力
print '' . $a . $b;
print "\n";
```

新人「わぁ、懐かしい…（しみじみ）
　　　あの、これが何か？」

遣付「**0点だ。**」

新人「手厳しい！」

遣付「このコードに追記してみよう。」

```perl:sinjin2_kai.pl
my $a = 0;
my $b = 1;
# 01を出力
print '' . $a . $b;
print "\n";

my @arr = (4, 9, 2, 8, 0, 1, 5, 6, 3, 7);

for my $v (sort {$a <=> $b} @arr){
    print $v;
}
```

新人「一体、何がまずいって言うん…**あっ！**」

遣付「気付いたか。
　　　`sort`イディオム中で使われる`$a`と`$b`は**グローバル変数**だ。
　　　上のコードを動かしても**期待通りにソートされない**事がわかる。」

```text:出力結果
01
4503261798
```

新人「そうか…この`$a`と`$b`は何だろう？と思いながらも
　　　**何となくソートを使っていましたが**、グローバル変数だったんですね。」

遣付「そう。無論、君のサンプルコードがなければ
　　　このコードは正常に動く。」

```perl:sinjin2_kai_kai.pl
my @arr = (4, 9, 2, 8, 0, 1, 5, 6, 3, 7);

for my $v (sort {$a <=> $b} @arr){
    print $v;
}
```

```text:出力結果
0123456789
```

遣付「`sort`についてはPerldocも合わせて確認しておくといい。」

[perlfunc - sort](https://perldoc.jp/func/sort)
[perlop - 等価演算子](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Equality32Operators)

新人「**ソートについての標準化**はしないのですか？」

遣付「なかなか根深いテーマなんでな…**泣く泣く**割愛させてもらう。」

新人「（めんどいんだな…）」

遣付「さて、話を戻そう。
　　　アルファベット一文字でグローバル変数として扱われるのは
　　　Perl本体では`$a`と`$b`だけだと思うが、
　　　例えば[Catalystフレームワーク](https://ja.wikipedia.org/wiki/Catalyst_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2))においては
　　　慣習的に`$c`がコンテキストオブジェクトを示す変数だったりする。」

新人「はぇ～。」

遣付「加えて、Perlには**アルファベット一文字の予約語が非常に多い**。
　　　演算子然り、コマンドのスイッチオプション然り。
　　　演算子なら例えば、[繰り返し演算子](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Multiplicative32Operators)`x`とか
　　　[正規表現のクォート風の演算子](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Regexp32Quote-Like32Operators)の置換`s///`とかね。」

新人「言われてみると確かにそうですね。」

遣付「じゃあ、**二文字以上ならいいのか？**という話だけど
　　　例えば[文字列比較演算子](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Equality32Operators)の`eq`とか`ne`とかは二文字だし、
　　　`cmp`は三文字だし…という事でキリがないので
　　　**とりあえず一文字変数だけ**を縛る事にしよう。
　　　`$a`と`$b`だけでもいいかもだけどね。」

新人「二文字もいずれ…ですかね。」

**二文字の演算子一例**
eq
ne
lt
le
gt
ge

遣付「だね。じゃあ次に進もう。」
　

#### 第八条：関数とサブルーチンの棲み分けをしておこう。

遣付「いよいよサブルーチンに足を突っ込んでいくわけだが…
　　　**関数とサブルーチンの違い**はわかるかな？」

新人「えっと、**サブルーチンは自分で作ったコード**、という事ですかね？」

遣付「実は、**曖昧**なんだ。」

>
明確な return 文のない関数はしばしばサブルーチンと 呼ばれますが、**Perl の定義上はこれらの間に何の違いもありません**
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

新人「おぉ！そうなんですね。」

遣付「ただ、こうも書いている。」

>
多くの言語と同様、Perl は**ユーザー定義のサブルーチン**を提供しています。 これらのサブルーチンは、メインプログラムのどこにでも置くことができ、 do, require, use といったキーワードを使って他のファイルから ロードすることができ、eval や無名サブルーチンを使って 生成することもできます。 サブルーチンの名前や、コードリファレンスを保持する変数を使って 間接的に**関数を呼び出すことも可能**です。
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

遣付「解釈の仕方は人それぞれかもしれないが、
　　　ここでは**便宜上**こう定義しておこう。」

###### 第八条 一項：自分で作成した関数を『サブルーチン』と呼称する。
###### 第八条 二項：perlfuncで規定されるAPI関数、およびモジュールないしサードパーティ製のライブラリで提供される関数を『関数』と呼称する。

新人「なるほど。自分で作った物がサブルーチンと。わかりやすいですね。」

遣付「ただ、ここのような大規模開発プロジェクトだと
　　　そこそこのボリュームの**API基盤**を内生することもある。
　　　それを『サブルーチン』と呼ぶか、『関数』と呼ぶかは意見が分かれるところだね。」

新人「ふむふむ。
　　　自分たちで作ったものであっても
　　　**基盤レベルまでAPIが昇華されているのなら『関数』と呼んだ方が適切かもしれない**
　　　という事ですね。」

遣付「そうだね。
　　　まぁ今はこんなもんでいいだろう。
　　　次にいこう。」
　

#### 第九条：サブルーチンの役割と用途は事前に打ち出そう。

遣付「自分で作る関数を**サブルーチン**と呼ぶと決めた所で質問だ。
　　　サブルーチンを作る**理由**は何だ？」

新人「理由…ですか？」

遣付「そう。」

新人「えっと…メインのサブルーチンが**長くなってしまう**から…とかですかね。」

遣付「それも理由の一つだろう。あとは？」

新人「うーんと、再利用性の高い部品を作っておくと**流用**が効くから…？」

遣付「それから？」

新人「えっと、えっと…」

遣付「そうなんだ。
　　　実は**とても大事なサブルーチンの大前提**に気付いていない人は結構多い。
　　　[構造化プログラミング](https://ja.wikipedia.org/wiki/%E6%A7%8B%E9%80%A0%E5%8C%96%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)の原理に則って
　　　順次、選択、反復の制御フローをブロック単位で小分けにして
　　　全体的なアルゴリズムの見通しをよくしたり、
　　　時には再利用性を高めたり、
　　　[スケーラビリティ](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%A9%E3%83%93%E3%83%AA%E3%83%86%E3%82%A3)を担保したり、
　　　というのは確かにサブルーチンの大きな**作用**であり**恩恵**だ。
　　　無論、その恩恵を得るために
　　　サブルーチンを作るというのはアプローチとしては決して間違っていない。
　　　が、それは**必要条件であって、十分条件ではない**んだよ。」

新人「？？？どういう事ですか？」

遣付「二つの命題`p`と`q`に対して、`pならばqである`が成り立つ時
　　　`p`を**十分条件**、`q`を**必要条件**と呼ぶ。

[必要十分条件（Wikipedia）](https://ja.wikipedia.org/wiki/%E5%90%8C%E5%80%A4#%E5%BF%85%E8%A6%81%E5%8D%81%E5%88%86%E6%9D%A1%E4%BB%B6)

　　　p`サブルーチンを作る然るべき理由がある。`
　　　ならば
　　　q`サブルーチンを作ったら再利用性が高まったり、見通しがよくなったりした。`
　　　なんだ。
　　　また、`pならばq`かつ`qならばp`が成り立つ状態を
　　　`pとqは同値である`と呼ぶ。
　　　この`p`と`q`が同値である時の`p`を**必要十分条件**と言うんだ。」

新人「必要十分条件…」

遣付「サブルーチンを作る理由が**必要十分条件であるべき**なのは言うまでもない。
　　　その理由が適切であったかどうかを振り返って評価する事もできるからね。

　　　q`サブルーチンを作ったら再利用性が高まったり、見通しがよくなったりした。`
　　　ならば
　　　p`サブルーチンを作る理由は適切であった（作成判断は正しかった）`

　　　これは[PDCA](https://ja.wikipedia.org/wiki/PDCA%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB)の観点から見ても正しいアプローチと言えそうだ。」

新人「なるほどー。」

遣付「では**然るべき理由**とは何か？
　　　理由は大きく**二つ**。」

新人「二つしかないんですか？」

遣付「あぁ。**そんなの当たり前じゃん？**と思う事かもしれないけど
　　　あえて声を大きくしておこう。
　　　まずは一つ目。」

###### 第九条 一項：既に存在するサブルーチンは作らない。

遣付「要は**なかったら作る。**当たり前だね。」

新人「じゃあ、**サブルーチンを長くしない為に作るサブルーチン**も
　　　**ないから作る**という理解で合っていますか？」

遣付「その通り。
　　　業務仕様的なサブルーチンの建て付けは
　　　API基盤でも存在しない限りは**作るしかない**からね。」

新人「なるほど。
　　　では、**ユーティリティ的なサブルーチン**はどう捉えればよいでしょうか？
　　　[ハッシュ関数](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E9%96%A2%E6%95%B0)のように一意な値を取得したり
　　　日付や数値など特定の仕様に基づいて加工したり
　　　という用途ですが…」

遣付「それが二つ目の理由だ。」

###### 第九条 二項：既に存在する関数ないしサブルーチンであっても、役割と用途を改善・拡張する形であれば、あらたにサブルーチンを作ってもよい。

新人「？？」

遣付「じゃあわかりやすく**関数**からいこう。
　　　PerlのAPIとして存在する関数があるとする。
　　　例えば`push`にしようか。」

[perlfunc - push](https://perldoc.jp/func/push)

遣付「`push`は第一引数に配列、第二引数にリストを取って
　　　対象の配列にリストを追加し、**追加された後の配列要素数を返却する**
　　　という関数だ。」

```perl:test28.pl
my @arr = ();

push @arr, '1';
my $len = push @arr , ('2', '3');
# 配列の中身「123」を出力
print @arr;
print "\n";
# 配列の長さ「3」を出力
print $len;
```

新人「へー。
　　　第二引数は厳密には`LIST`なんですね。
　　　あと、要素数を返す作用も知りませんでした。
　　　てっきり配列にスカラを追加するだけの関数かと…。」

遣付「既存のコードでも`push ARRAY, SCALAR;`で
　　　リストも渡さないし、戻り値を受け取らないケースがほとんどだから、
　　　そう思うのも仕方ない。
　　　ただね、何かの勘違いで
　　　君が`push`的なサブルーチンを**自分で構築しちゃった**としよう。
　　　恐らくその認識下では
　　　**第二引数はスカラしか許容しない**し
　　　**戻り値も存在しない**という**デグレードした`push`が出来上がる**はずだ。」

新人「あぁ…確かに。」

遣付「たとえ、デグレードしない形で作れたとしても
　　　**既存の関数ないしサブルーチンと同じものを作る時間はムダでしかない**よね。
　　　なので、サブルーチンを構築する前には
　　　**同じものがあるかないか？**を必ず確認する癖をつけよう。」

新人「わかりました。」

遣付「同じものがあるかないかの判断材料になるのは
　　　冒頭の記載通り、**役割**と**用途**だ。
　　　自分が作ろうと思っているサブルーチンは
　　　**何を引数**に取って
　　　**何に対して何を施し**
　　　**何を返す**サブルーチンなのか？
　　　という事を示すのが**役割**だ。
　　　結果的に、そのサブルーチンが新たにできる事で
　　　**どう嬉しくてどのシーンで使える？**というのが**用途**だ。」

新人「なるほど。
　　　じゃあ例えば既存の関数ないしサブルーチンに
　　　**不足している致命的な機能**があった場合に
　　　**機能追加する**形であらたにサブルーチンを作るのはアリって事でしょうか？」

遣付「そうだね。
　　　でもその場合、**既存のものを修正できない**という**根拠**もある程度は必要だ。
　　　関数であればどうしようもないが
　　　**既存のサブルーチンであれば、修正する**という指針もあるはずだ。
　　　もし、修正できないとするのであれば
　　　例えば、修正した場合の影響範囲・リスクが大き過ぎる、などの
　　　理由付けは必要だろう。」

新人「あぁ。
　　　確かに既存サブルーチンを参照している側で
　　　デグレが起きる可能性もなくはないですもんね。」

遣付「その通り。
　　　つまりは、だ。
　　　開発のスキームにおいては**役割と用途を拡張する**のがサブルーチンなんだ。
　　　既にあるものは作る必要ないし
　　　逆になければ作る、非常にシンプルだよね。
　　　だからどんなに小さなサブルーチンであっても
　　　既存のありなしを判定する意味でも
　　　**サブルーチンを作成する前にその役割と用途を洗い出すべき**だ。」

新人「なるほど！腑に落ちました！」
　

#### 第十条：サブルーチンの引数はわかりやすくそしてシンプルに。

遣付「じゃあ早速サブルーチンを作成していくよ。
　　　戻り値は次の条で詳しくやるので、
　　　ひとまずここでは**戻り値を考えない**事にする。
　　　サンプルとは言え、せっかくなので**役割**と**用途**を書いておこう。

役割：引数を**複数**受け取ってその内容を`print`する。
用途：サンプル実行のため。（業務では使用しない）

新人「この**複数**が苦手なんですよね…」

遣付「まぁまぁ。一つ一つ、段階を踏んでやっていこう。
　　　まずはperlsubを確認してみるよ。」

>
Perl での関数呼び出しと戻り値のモデルは単純です。全ての関数は引数を、 **平坦で一つのスカラのリストで受け取り**、同様に全ての関数は呼び出し元に 対して平坦で一つのスカラのりストで返すというものです。 
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

遣付「続いてこうある。」

>
ルーチン（※）に渡されるすべての引数は**配列 @_**に置かれます。 
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
※**著者注：たぶんサブルーチンの誤訳**。原文「Any arguments passed in show up in the array @_. 」
>

遣付「つまり引数の基本は**スカラの配列**なんだ。」

```perl:test29.pl
sub sample{
    print @_;
}

# 1234を出力
sample(1, 2, 3, 4);

my @arr = (5, 6, 7);
# 567を出力
sample(@arr);
```

新人「なるほど。
　　　`リスト`を受け取って`@_`配列に格納される、という事ですね。
　　　**サブルーチンを呼び出す際のカッコ**は必須ですか？」

```perl
# カッコなしでも呼べるけど…
sample @arr;
```

遣付「必須ではないけど**カッコがあった方がいい**ね。
　　　**慣習的に**関数呼び出しはパラメータをスペースで区切る
　　　というのは前に言った通りだけど
　　　カッコがあるだけで関数ではなくサブルーチンというのがわかるし。
　　　**特別な事情がない限りはカッコを付ける**ようにしよう。」

###### 第十条 一項：サブルーチンの呼び出し時はカッコを付ける。`subroutine(PARAM)`

新人「そういえばPerlには**[名前付き仮引数](https://ja.wikipedia.org/wiki/%E5%BC%95%E6%95%B0#%E4%BB%AE%E5%BC%95%E6%95%B0)**という概念はないのでしょうか？」

遣付「うん。version5においては基本的には**ない**という認識でいい。
　　　version6はあるみたいだけど…。
　　　version5.20以降だと一応、**シグネチャ**という機能はあるんだけど
　　　これも**実験的**なAPIだから使わないのがベターだろうね。

>
**実験的な機能 (後述の "Signatures" 参照) を除いて、Perl は名前付き仮引数を 持っていません。**my() にこれらのリストを代入することで行えます。 
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

遣付「あと名前付き仮引数ではないけど、**プロトタイプ**という考え方がある。」

>
Perl はとても限られた形のコンパイル時引数チェックに対応しています。 これは PROTO セクションか プロトタイプ属性 で宣言できます。 以下のどちらかのように宣言すると:
    sub mypush (\@@)
    sub mypush :prototype(\@@)
mypush() は push() が取るのとまったく同じ引数を取ります。
[perlsub - Perl のサブルーチン - プロトタイプ](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#Prototypes)
>

遣付「**中途半端に静的型付けのようなマネをするメリットがよくわからない**し、
　　　逆に**見通しがよくなるわけでもない**ので
　　　プロトタイプを使うのはやめよう。」

###### 第十条 二項：サブルーチンプロトタイプは使わない。

新人「ふむふむ。
　　　`@_`を前提にサブルーチンの引数を処理していくという形で理解しました。
　　　でも**`$_`はわかりずらいし使いたくない**ですね…
　　　どうすればよいでしょうか？」

```perl:test30.pl
sub sample{
    # 見づらい
    print $_[0];
    print $_[1];
    print $_[2];
}

sample(1, 2, 3);
```

遣付「一般的には**my**を使って**レキシカル変数**に入れてしまうのがよいとされているね。
　　　**my**という演算子を今まで普通に使っていたけど
　　　これは**その宣言をしたスコープでしか使えない**という意味なんだ。」

>
**my 演算子**は、それを囲んでいるブロック、条件文 (if/unless/elsif/else)、ループ (for/foreach/while/until/continue)、**サブルーチン**、eval、 あるいは do/require/use されたファイルに**レキシカル**に閉じ込められる 変数を定義します。
[perlsub - Perl のサブルーチン - my() によるプライベート変数](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#Private32Variables32via32my40-41)
>

新人「なるほどー。」

遣付「また、**リスト値のコンストラクター**の仕様に準拠すると…」

>
リスト自身を構成する個々の要素すべてに代入が許される場合にのみ、**全体のリストに代入を行なう**ことができます:
[perldata - Perl のデータ型 - リスト値のコンストラクター](https://perldoc.jp/docs/perl/5.26.1/perldata.pod#List32value32constructors)
>

```perl
my $x;
my $y;
my $z;

# 左辺のリストと右辺のリストの要素数が同じ。
($x, $y, $z) = (1, 2, 3);

# 左辺より右辺の要素が多い場合は切り捨て。
# $xに1が、$yに2が代入されて、3は使われない。
($x, $y) = (1, 2, 3);

# 左辺より右辺の要素が少ない場合は一部の値が代入されない。
# 厳密には、$xには1が、$yには2が、$zには未定義値（undef）が代入される。
($x, $y, $z) = (1, 2);

# 未定義値なので↓はエラーになる。
# print $z;
```

遣付「こんな風に書けるという事だ。」

```perl:test31.pl
sub sample{
    # それぞれの引数をレキシカル変数に代入
    my ($name, $age, $gender) = @_;
    print $name."\n";
    print $age."\n";
    print $gender."\n";
}

sample('Hogeyama Fugataro', 25, 'gentle man');
```

新人「ふむふむ。」

遣付「要は**要素の個数が合ってりゃいい**って事なんで
　　　下のようにも書けるよ。」

```perl:test32.pl
sub sample{
    # 引数をそのまま配列としてレキシカル変数に代入。
    my @param = @_;
    print @param;
}

my @lower_alphabet = ('a' .. 'z');
# aからzまでを出力
sample(@lower_alphabet);
```

```perl:test33.pl
sub sample{
    # 引数の一番目、二番目をスカラとして代入、残りを配列で代入。
    my ($name, $age, @personality) = @_;
    # $nameを出力
    print $name."\n";
    # $ageを出力
    print $age."\n";
    # $nameと$ageを除いた残りの@_を出力
    print join "\n", @personality;
}

sample('Hogeyama Fugataro', 25, 'gentle man', 'handsome', 'friendly', 'high-income');
```

新人「引数の受けが基本的に**配列`@_`**なので、
　　　配列を渡す時は直感的にわかりやすいですね。
　　　ただ**ハッシュ**の場合はどうすればよいのでしょう？」

遣付「じゃあ寄り道してハッシュをちょっとだけ詳しくみてみよう。
　　　まずPerlのハッシュ実装は**ハッシュテーブル**というデータ構造に基づいている。」

>
ハッシュテーブル (英: hash table) は、**キーと値の組（エントリと呼ぶ）を複数個格納し**、キーに対応する値をすばやく参照するためのデータ構造。ハッシュ表ともいう。ハッシュテーブルは連想配列や集合の効率的な実装のうち1つである。
([Wikipedia](https://ja.wikipedia.org/wiki/ハッシュテーブル)より抜粋)
>

遣付「Javaだと例えば`HashMap`、Pythonだと辞書型、などなど
　　　他の言語でも使われている有名なデータ構造だね。」

[プログラミング言語におけるハッシュテーブルの実装（Wikipedia）](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AE%E5%AE%9F%E8%A3%85)

新人「そうですね。」

遣付「でも思い出してみて欲しい。
　　　Perlのハッシュを初期化する時はどうするのが普通だ？」

新人「えっと、ファットコンマでキーとバリューを繋ぐんでしたね。
　　　あれ？でも、ファットコンマ`=>`って普通のコンマ`,`と同義だから…
　　　これ…！よくよく見たら**リストでハッシュを初期化**しています。」

```perl:test6.pl
my %hash1 = ('a', 1, 'b', 2, 'c', 3);
my %hash2 = (a=>1, b=>2, c=>3);
```

遣付「その通り。
　　　配列と同じように、ハッシュも**リスト代入**ができるんだ。
　　　簡単に言えば`()`で括られていて、`,`で区切られているものが**リスト**だ。
　　　直感的に勘違いしやすいんだけど、**配列＝リストではない**。
　　　配列はデータ型だが、**リストはただの表記方法**に過ぎないんだ。

>
**リスト値**は、**個々の値をコンマで区切って (必要に応じて括弧で括って) 示されます**
[perldata - - リスト値のコンストラクター](https://perldoc.jp/docs/perl/5.26.1/perldata.pod#List32value32constructors)
>

新人「あ。配列とリストを混同していたかもしれないです。お恥ずかしい…」

遣付「つまりは配列もハッシュもリスト代入が可能という事だから
　　　例えばハッシュを配列にしたい場合は
　　　**単純に代入すればよいだけ**だね。」

```perl:test34.pl
# ハッシュを宣言して初期化。
my %hash = (a => 1, b => 2, c => 3);
# ハッシュを配列に代入
my @arr = %hash;
# c3a1b2を出力。（ただしハッシュテーブルなので順番は不定）
print @arr;
print "\n";
```

新人「はぇ～」

遣付「また例えばハッシュをループで回す時には
　　　`keys`関数や`values`関数がよく使われるけど、その仕組みについて
　　　**ハッシュテーブルというブラックボックスにアクセスして**
　　　**キーをごにょごにょしたりバリューをごにょごにょしたりして**
　　　**特定の値を引っ張ってきてくれている**
　　　と無駄に難しく考えるよりかは
　　　**ハッシュをリスト値と捉えた上で**
　　　**`keys`は0を含む偶数番目のインデックス値**を
　　　**`values`は奇数番目のインデックス値**を
　　　**持ってきてくれている**
　　　と考えた方がシンプルじゃないかなぁとは思う。
　　　厳密には違うかもだけどね。」

```perl:test35.pl
# ハッシュを宣言して初期化
my %hash = (a => 1, b => 2, c => 3);
# ↓と同義
# my %hash = ('a', 1, 'b', 2, 'c', 3);
# keys関数でループ
for my $k (sort keys %hash){
    # abcを出力（リスト上のインデックスは0, 2, 4）
    print $k;
    print "\n";
}

# values関数でループ
for my $v (sort values %hash){
    # 123を出力（リスト上のインデックスは1, 3, 5）
    print $v;
    print "\n";
}

# keys関数を使ってキーとバリューと両方抜く。
for my $k (sort keys %hash){
    # それぞれのキーとバリューを出力
    print "key: $k, value: $hash{$k}";
    print "\n";
}
```

[perlfunc - sort](https://perldoc.jp/func/sort)
[perlfunc - keys](https://perldoc.jp/func/keys)
[perlfunc - values](https://perldoc.jp/func/values)

遣付「ちなみに、上の`keys`と`values`のPerldocを見てもらうとわかる通り
　　　Perlのバージョン5.12以降では、`each`関数よろしく
　　　ハッシュだけでなく配列に対しても`keys`と`values`が使えるから
　　　リスト値の偶数番目のインデックス、奇数番目のインデックスという考え方は
　　　配列に対しては適切ではなくなるけど、まぁこの現場は5.10.1だし。（震え声）」

新人「（また、すねてる…）」

遣付「閑話休題。
　　　ハッシュをサブルーチンの引数として渡したい場合は
　　　もうわかるよね？」

新人「はい！こうですね！」

```perl:test36.pl
sub sample{
    # 引数をそのままハッシュとしてレキシカル変数に代入。
    my %param = @_;
    print %param;
}

my %hash = (a=>1, b=>2, c=>3);
# c3a1b2を出力。（ただしハッシュテーブルなので順番は不定）
sample(%hash);
```

遣付「その通り。つまりここまでの結論としてはこうだ。」

###### 第十条 三項：単純にリスト値として渡せる引数（配列、ハッシュ）はそのままレキシカル変数にリスト代入する。

新人「という事は**単純にいかないケース**があるという事ですね？」

遣付「察しがいいな。
　　　例えば、配列を二つ渡したい場合だ。」

```perl:test37.pl
sub sample{
    my (@param1, @param2) = @_;
    print "param1:";
    print @param1;
    print "\n";
    print "param2:";
    print @param2;
}

my @arr1 = (1, 2, 3);
my @arr2 = (4, 5, 6);

sample(@arr1, @arr2);
```

```text:出力結果
param1:123456
param2:
```

新人「あれ？`param1`に全部入っちゃいました。」

遣付「そう。
　　　呼び出し元では二つの配列に分けているつもりでも
　　　サブルーチンで受け取った時は一つのリスト値として評価されてしまう。
　　　引数は**`@_`にリスト値として丸ごと展開されてしまう**から
　　　呼び出し元の引数の切れ目がわかんなくなってしまう、という事だね。」

新人「うーん。どうすればいいでしょう。」

遣付「そこで思い出してほしい。
　　　サブルーチンの引数は**スカラのリスト**である事を。
　　　逆に言えば、スカラとして区別がされているのであれば
　　　呼び出し先でもその切れ目を判断できる、という事だ。
　　　つまり、**スカラとして配列を表現できればいい**よね。」

新人「なるほど！**リファレンス**ですね。」

遣付「正解！」

>
これらの呼び出しリストと戻り値リストにある全ての配列とハッシュは、 潰されてそのアイデンティティを失います。 **しかし、これを避けるために常にリファレンスで渡すことができます。**
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

```perl:test38.pl
sub sample{
    # スカラを二つ受け取る。
    my ($param1, $param2) = @_;
    print "param1:";
    # デリファレンスする
    print @{$param1};
    print "\n";
    print "param2:";
    # デリファレンスする
    print @{$param2};
}

my @arr1 = (1, 2, 3);
my @arr2 = (4, 5, 6);

# スカラを二つ渡す。（リファレンスはスカラである。）
sample(\@arr1, \@arr2);
```

```text:出力結果
param1:123
param2:456
```

新人「ふむふむ。
　　　**スカラとして区別がついていればよい**という事ですね。
　　　じゃあ、例えばこんなのも…」

```perl:test39.pl
sub sample{
    my ($param1, $param2, %param3) = @_;
    print "param1:";
    print $param1;
    print "\n";
    print "param2:";
    print $param2;
    print "\n";
    print "param3:";
    print %param3;
}

sample('aiueo', 'kakikukeko', 'A' => 1, 'B' => 2, 'C' => 3);
```

```text:出力結果
param1:aiueo
param2:kakikukeko
param3:A1C3B2
```

新人「…こんなのも」

```perl:test40.pl
sub sample{
    my ($param1, $param2, $param3) = @_;
    print "param1:";
    print $param1;
    print "\n";
    print "param2:";
    print @{$param2};
    print "\n";
    print "param3:";
    print %{$param3};
}

my $str = 'aiueo';
my @arr = (1, 2, 3);
my %hash = ('A' => 1, 'B' => 2, 'C' => 3);
sample($str, \@arr, \%hash);
```

```text:出力結果
param1:aiueo
param2:123
param3:A1C3B2
```


新人「…動くということか！」

遣付「いいぞいいぞ。」

###### 第十条 四項：配列やハッシュを複数、引数として渡したい場合はリファレンスを使う。

遣付「あと、補足するなら**引数がスカラ変数一つの場合**だね。
　　　`shift`関数を使うと便利だ。」

>
shift ARRAY
shift
**配列の最初の値を取り出して、その値を返し**、配列を一つ短くして、すべての要素を 前へずらします。 配列に要素がなければ、未定義値を返します。 **ARRAY を省略すると、サブルーチンやフォーマットのレキシカルスコープでは @_ を**、サブルーチンの外側で、eval STRING, BEGIN {}, INIT {}, CHECK {}, UNITCHECK {}, END {} で作成された レキシカルスコープでは @ARGV が用いられます。
[perlfunc - shift](https://perldoc.jp/func/shift)
>

```perl:test41.pl
sub sample{
    my $param = shift @_;
    # @_は省略可能。
    # my $param = shift;
    # リスト代入でも同じ事が行える
    # my ($param) = @_;
    print $param;
}

sample('aaa');
```

新人「これは`shift`一つだけの方がわかりやすいかもですね。」

遣付「そうだね。
　　　慣れない内はリスト代入`my ($param) = @_;`でもいいと思うけど
　　　折角なので標準化しておこうか。」

```perl:test41_kai.pl
sub sample{
    my $param = shift;
    print $param;
}

sample('aaa');
```

###### 第十条 五項：引数がスカラ変数一つの場合は`@_`を省略し、`shift`関数で受ける。

遣付「引数についてはこんなもんかな。
　　　じゃあ戻り値にいこう。」

新人「オッケーです！」
　

#### 第十一条：サブルーチンの戻り値はreturnかdieでキメよう。

遣付「戻り値…一般的には**返り値**や**リターン値**とも呼ばれたりするね。
　　　**Perldocでは『戻り値』と呼ばれている事が多い**ので
　　　以降は戻り値と呼称する事にする。」

新人「わかりました。」

遣付「さて、じゃあ大事な大前提を最初にぶち上げておこう。
　　　**Perlにおいては基本的に戻り値のないサブルーチンは存在しない。**」

新人「えぇぇ！？そうなんですか？」

遣付「あぁ。次を見てくれ。」

```perl:test42.pl
sub sample{}

my $ret = sample();
print $ret;
# Use of uninitialized value $ret in printエラーを出力。
```

新人「`$ret`が未定義だと怒られていますね…
　　　`sample`サブルーチンが**何も返していないから**ではないんですか？」

遣付「よし。じゃあ`$ret`を初期化しておこうか。」

```perl:test42.pl
sub sample{}

my $ret = 'ABC';
$ret = sample();
print $ret;
# Use of uninitialized value $ret in printエラーを出力。
```

新人「んんん？同じですね？」

遣付「わかったろう。
　　　空の`sample`サブルーチンは**未定義値を返却している**んだ。」

>
**もし何の戻り値も指定しなければ**、サブルーチンはリストコンテキストにおいては 空リストを返し、**スカラコンテキストにおいては未定義値を返し**、 無効コンテキストではなにも返しません。
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

遣付「明示的にも記載されているね。」

>
**空のサブルーチンは空リストを返します。**
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

新人「サブルーチンの中に何も書かれていないと
　　　**空リスト、つまり未定義値が返る**のはわかりました。
　　　では第十条でサンプルプログラムとして扱っていた
　　　**`print`しかしないサブルーチンは何が返っている**のですか？」

```perl:test41_kai.pl
sub sample{
    my $param = shift;
    print $param;
}

sample('aaa');
```

遣付「うん。じゃあ、やってみようか。」

```perl:test41_kai_kai.pl
sub sample{
    my $param = shift;
    print $param."\n";
}

my $ret = sample('aaa');
print "Content of \$ret is [${ret}].";
```

```text:出力結果
aaa
Content of $ret is [1].
```

新人「1？
　　　**1って何ですか？**」

遣付「`print`関数の戻り値だ。」

新人「`print`の戻り値？」

>
文字列か文字列のリストを出力します。 **成功時には真を返します。**
[perlfunc - print](https://perldoc.jp/func/print)
>

遣付「そしてこうだ。」

>
return がなく、**最後の文が式だった場合、その値が返されます。** 最後の文が foreach や while のようなループ制御構造だった場合、 返される値は不定です。 
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

新人「はぁ…最後の式の**評価**が返っているという事ですか。
　　　これはわかりずらいですね。
　　　ちなみに**無効コンテキスト**というのは何でしょう？」

>
もし何の戻り値も指定しなければ、サブルーチンはリストコンテキストにおいては 空リストを返し、スカラコンテキストにおいては未定義値を返し、 **無効コンテキストではなにも返しません**。
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

遣付「無効コンテキストというのは
　　　評価した結果を利用しない、つまり**値を期待しないコンテキスト**だ。
　　　例えばこんな。」

```perl
'aiueo';
```

遣付「サブルーチンを呼び出す時も同様に
　　　**戻り値を呼び出し側で受けない形は無効コンテキスト**となる。」

```perl
subroutine(PARAM);
```

新人「なるほど。」

遣付「つまり、こういう事だ。」

```perl
sub sample(){}
sample();
```

遣付「この場合**戻り値としては何も返さない**し
　　　呼び出し元でも**何もしない**という事だね。
　　　サブルーチンの中身が空でなくても同じだ。
　　　無効コンテキストの場合は何も返さない。」

```perl:test47.pl
#!/usr/bin/perl
use strict;
use warnings;

sub sample{
    # 無効コンテキスト
    # Useless use of a constant in void context警告は出力されない。
    # （サブルーチンの中だから）（よくわからんがそういうもんだと思おう。）
    'aaa';
}

# 無効コンテキスト
# Useless use of a constant in void context警告を出力。
'bbb';

# 無効コンテキスト
# 何も返されないので何もしない。
sample();

# スカラコンテキスト
# 式評価として'aaa'が返ってくる。
my $ret1 = sample();
print '$ret1 is [';
print $ret1;
print "]\n";

# リストコンテキスト
# 式評価として'aaa'が返ってくる。
my @ret2 = sample();
print '@ret2 is [';
print @ret2;
print "]\n";
```

```text:出力結果
Useless use of a constant in void context at C:/perltest/test47.pl line 14.
$ret1 is [aaa]
@ret2 is [aaa]
```

新人「ふむふむ。…なかなかややこしいですね。」

遣付「そう。
　　　だから値を返さないサブルーチン、
　　　つまり**無効コンテキストで実行される事が期待されるサブルーチンを作る**場合は
　　　明示的に`return;`を書くようにしよう。」

```perl:test41_kai_kai_kai.pl
sub sample{
    my $param = shift;
    print $param."\n";
    return;
}

my $ret = sample('aaa');
print "Content of \$ret is [${ret}].";
```

```text:出力結果
aaa
Use of uninitialized value $ret in concatenation (.) or string at C:/perltest/test41_kai_kai_kai.pl line 12.
Content of $ret is [].
```

新人「あれ？
　　　`return;`を追記しただけなのにエラーが出るようになってしまいましたね。
　　　これは…？」

遣付「perldocを見よう。」

>
return EXPR
return
サブルーチン, eval, do FILE, sort ブロックまたは正規表現 eval ブロック (但し grep や map ブロックではない) から **EXPR で与えられた値をもって、リターンします。** EXPR の評価は、返り値がどのように使われるかによってリスト、スカラ、 無効コンテキストになります; またコンテキストは実行毎に変わります (wantarray を参照してください)。 **EXPR が指定されなかった場合は、リストコンテキストでは空リストを、 スカラコンテキストでは未定義値を返します**; そして(もちろん) 無効コンテキストでは何も返しません。
[perlfunc - return](https://perldoc.jp/func/return)
>

遣付「引数のない`return;`は未定義値を返す。
　　　順番を考えれば
　　　『役割と用途をしっかりと建て付けてサブルーチンを作る』
　　　の後に
　　　『サブルーチンを呼び出して使う』
　　　だよね。
　　　元々、`return;`で戻り値を建て付けたという事は
　　　このサブルーチンは**未定義値を戻り値とする**仕様だ。
　　　つまり、戻り値を期待して
　　　`my $ret = sample();`という風に呼び出している
　　　この**使い方が悪い**という事になるよね。」

新人「あー。なるほど。
　　　逆に**間違った使い方をすればエラーが起きる**と。」

遣付「そうだ。
　　　そもそも未定義値が戻る事がわかっているのであれば
　　　**わざわざ戻り値を受ける必要はない**よね。」

```perl:test41_kai_kai_kai_kai.pl
sub sample{
    my $param = shift;
    print $param."\n";
    return;
}

sample('aaa');
```

```text:出力結果
aaa
```

新人「確かに。これなら呼び出し方も一目瞭然ですし
　　　サブルーチンを読んだ後に**未定義値に触ってしまうリスクも少なそう**です。

###### 第十一条 一項：戻り値のないサブルーチンは`return;`を最低限必ず書く。
###### 第十一条 二項：`return;`でしか戻さないサブルーチンの戻り値をレキシカル変数で受けない。

遣付「じゃあ今度は戻り値を返す`return EXPR;`について考えてみよう。」

```perl:test43.pl
sub sample{
    return 100;
}

my $ret = sample();
print $ret;
```

新人「はい。スカラの100が戻ってきてprint…これは単純ですね。」

遣付「じゃあ配列とハッシュはどうだろうか。」

```perl:test44.pl
sub sample1{
    my %sample1_ret = (hoge => 1, fuga => 2);
    return %sample1_ret;
}

sub sample2{
    my @sample2_ret = (1, 2, 3, 4);
    return @sample2_ret;
}

my %ret1 = sample1();
print %ret1;
print "\n";

my @ret2 = sample2();
print @ret2;
print "\n";
```

新人「これも問題なさそうですね。」

遣付「…なんだけど、**配列とハッシュはできるだけリファレンスで返した方がよい**。」

新人「どうしてですか？」

遣付「**サブルーチンの引数はリストが基本**というのと同じように
　　　**サブルーチンの戻り値はスカラが基本**としておいた方がシンプルだからだね。」　

```perl:test44_kai.pl
sub sample1{
    my %sample1_ret = (hoge => 1, fuga => 2);
    return \%sample1_ret;
}

sub sample2{
    my @sample2_ret = (1, 2, 3, 4);
    return \@sample2_ret;
}

my $ret1 = sample1();
print %{$ret1};
print "\n";

my $ret2 = sample2();
print @{$ret2};
print "\n";
```

遣付「あとは、例えば**どうしても配列とハッシュを複数戻したい**場合は
　　　リスト代入でリファレンスを複数受け取る事もできる。」

```perl:test44_kai_kai.pl
sub sample{
    my %sample1_ret = (hoge => 1, fuga => 2);
    my @sample2_ret = (1, 2, 3, 4);
    return (\%sample1_ret, \@sample2_ret);
}

my ($ret1, $ret2) = sample();
print %{$ret1};
print "\n";
print @{$ret2};
print "\n";
```

新人「そうか。
　　　別にリスト代入は引数を受け取る為だけのものではないですもんね。」

遣付「複数の戻り値が必ずしもスマートかというと**微妙**だけどね。」

新人「スカラとして何が戻ってくるかは意識しておく必要がありますが
　　　できるだけスカラの形がシンプルという事は理解しました。」

###### 第十一条 三項：サブルーチンの戻り値は（できるだけ）スカラで返す。
###### 第十一条 四項：やむを得ずリストの戻り値を定義したい場合は、スカラのリストとする。

遣付「ここで第九条をもう少し深堀してみよう。」

>
第九条：サブルーチンの役割と用途は事前に打ち出そう。
>

遣付「注目してほしいのは**役割**と`return`文の関係だ。
　　　直前でやった通り
　　　戻り値がある場合は`return EXPR;`で返すよね。」

```perl:test43.pl
sub sample{
    return 100;
}

my $ret = sample();
print $ret;
```

新人「はい。そうですね。」

遣付「その前段としてそもそも**`return;`と`return EXPR;`のどちらで建て付けるか？**
　　　という決めが大事なんだ。」

新人「どういう事でしょうか？」

遣付「以下の要件を考えてみよう。
　　　演習なので**サブルーチンを作る前提**で進めるものとする。」

＜要件＞
１．ハッシュAに**固定値が入ったハッシュB**の内容を追加したい。
　　ハッシュAの内容：キーがランダムで何が入っているかはわからない。
　　ハッシュBの内容：`foo`、`bar`、`baz`の３つのキーバリューを保持している。
２．ただし、ハッシュAに`foo`、`bar`、`baz`のキーの**いずれか**が既に存在する場合
　　既存以外のキー値、バリュー値のみをハッシュAに追加する。
３．ハッシュAに`foo`、`bar`、`baz`のキーの**全て**が存在する場合
　　全てのキーを上書きする形でハッシュAのバリュー値を更新する。

|ハッシュAのfoo|ハッシュAのbar|ハッシュAのbaz|挙動|
|:-:|:-:|:-:|:-:|
|存在しない|存在しない|存在しない|ハッシュBの内容をハッシュAに全て追加|
|存在しない|存在しない|存在する|fooとbarのみをハッシュAに追加|
|存在しない|存在する|存在しない|fooとbazのみをハッシュAに追加|
|存在しない|存在する|存在する|fooのみをハッシュAに追加|
|存在する|存在しない|存在しない|barとbazのみをハッシュAに追加|
|存在する|存在しない|存在する|barのみをハッシュAに追加|
|存在する|存在する|存在しない|bazのみをハッシュAに追加|
|存在する|存在する|存在する|ハッシュBの内容でハッシュAを全て更新|

新人「ぐぬぬ…なかなか厄介ですね。とりあえずやってみます。」

カタカタカタカタカタカタカタカタカタカタカタカタカタカタ

新人「これでどうでしょう！」

```test44_sinjin.pl
# ハッシュB
my %hash_b = (foo => 100, bar => 200, baz => 300);

# 追加する対象を返却するサブルーチン
sub get_additive_for_hash_a{
    my $ref_hash_a = shift;
    my %ret = ();
    my $cnt = 0;
    for my $key (keys %hash_b){
        if(exists ${$ref_hash_a}{$key}){
            $cnt++;
        }
    }
    if($cnt == 0 || $cnt == 3){
        %ret = %hash_b;
    }else{
        for my $key (keys %hash_b){
            if(! exists ${$ref_hash_a}{$key}){
                $ret{$key} = $hash_b{$key};
            }
        }
    }

    return \%ret;
}

# 8パターンのハッシュA
my %hash_a1 = (aiueo => 1, kakikukeko => 2);
my %hash_a2 = (aiueo => 1, kakikukeko => 2, baz => 3);
my %hash_a3 = (aiueo => 1, kakikukeko => 2, bar => 3);
my %hash_a4 = (aiueo => 1, kakikukeko => 2, bar => 3, baz => 4);
my %hash_a5 = (aiueo => 1, kakikukeko => 2, foo => 3);
my %hash_a6 = (aiueo => 1, kakikukeko => 2, foo => 3, baz => 4);
my %hash_a7 = (aiueo => 1, kakikukeko => 2, foo => 3, bar => 4);
my %hash_a8 = (aiueo => 1, kakikukeko => 2, foo => 3, bar => 4, baz => 5);

my @test_data = ();
push @test_data, \%hash_a1;
push @test_data, \%hash_a2;
push @test_data, \%hash_a3;
push @test_data, \%hash_a4;
push @test_data, \%hash_a5;
push @test_data, \%hash_a6;
push @test_data, \%hash_a7;
push @test_data, \%hash_a8;

# メイン処理
for my $ref_hash (@test_data){
    my $additive = get_additive_for_hash_a($ref_hash);
    my %hash_a = (%{$ref_hash}, %{$additive});
    print %hash_a;
    print "\n";
}
```

遣付「なるほど。では作ったサブルーチンの役割を説明してくれ。」

新人「えっと、ハッシュAを引数として受け取って、
　　　ハッシュBのキーと突合し、
　　　**ハッシュAに追加するべきハッシュのリファレンスを戻り値とする**
　　　サブルーチンです。」

遣付「ふむふむ。
　　　**要件だけ満たす事を考える**のであれば
　　　こういう風にも書けるだろう？」

カタカタカタカタカタカタ…ッターン！

```perl:test44_yattuke.pl
# ハッシュB
my %hash_b = (foo => 100, bar => 200, baz => 300);

# ハッシュAに加工を施すサブルーチン
sub modify_hash_a{
    my $ref_hash_a = shift;
    my $cnt = 0;
    for my $key (keys %hash_b){
        if(exists $ref_hash_a->{$key}){
            $cnt++;
        }
    }

    if($cnt == 0 || $cnt == 3){
        %{$ref_hash_a} = (%{$ref_hash_a}, %hash_b);
    }else{
        for my $key (keys %hash_b){
            if(! exists $ref_hash_a->{$key}){
                $ref_hash_a->{$key} = $hash_b{$key};
            }
        }
    }

    return;
}

# 8パターンのハッシュA
my %hash_a1 = (aiueo => 1, kakikukeko => 2);
my %hash_a2 = (aiueo => 1, kakikukeko => 2, baz => 3);
my %hash_a3 = (aiueo => 1, kakikukeko => 2, bar => 3);
my %hash_a4 = (aiueo => 1, kakikukeko => 2, bar => 3, baz => 4);
my %hash_a5 = (aiueo => 1, kakikukeko => 2, foo => 3);
my %hash_a6 = (aiueo => 1, kakikukeko => 2, foo => 3, baz => 4);
my %hash_a7 = (aiueo => 1, kakikukeko => 2, foo => 3, bar => 4);
my %hash_a8 = (aiueo => 1, kakikukeko => 2, foo => 3, bar => 4, baz => 5);

my @test_data = ();
push @test_data, \%hash_a1;
push @test_data, \%hash_a2;
push @test_data, \%hash_a3;
push @test_data, \%hash_a4;
push @test_data, \%hash_a5;
push @test_data, \%hash_a6;
push @test_data, \%hash_a7;
push @test_data, \%hash_a8;

# メイン処理
for my $ref_hash (@test_data){
    modify_hash_a($ref_hash);
    print %{$ref_hash};
    print "\n";
}
```

遣付「このサブルーチンの役割は
　　　ハッシュAを引数として受け取って、
　　　ハッシュBのキーと突合するまでは同じだが、
　　　**ハッシュAにダイレクトに更新をかける**というサブルーチンだ。
　　　元値を変えてしまうので戻り値は不要となり`return;`となる。
　　　もしくは、サブルーチン処理自体の成否を示す
　　　**リターンコードを`return EXPR;`で返してもいい**かもね。」

新人「なるほど！
　　　これでも要件を満たせますね！」

遣付「例えばだが、
　　　順序を入れ替えたい加工用サブルーチンの作成がいくつか想定されていたり、
　　　もしくは、順序不問の加工要件の死活をサブルーチン呼び出しの有無で制御したり、
　　　といった**用途**を前提にアルゴリズムを建て付けたい場合は有効に働くね。
　　　ただ、**元値を更新してしまうという大きな作用**があるので
　　　取扱いには十分注意しなくてはいけない。」

新人「ふむふむ。」

遣付「このように、
　　　要件によっては**`return;`と`return EXPR;`のどちらが適切なのか？**
　　　というのが変わってくるんだ。
　　　**サブルーチンの役割と用途というのは
　　　最初に建て付けた後はできる限り変えない方が望ましい。**」

新人「確かに。**戻り値の扱いも全然変わっちゃいます**しね。」

遣付「そう。上の例では戻り値の様式が変わるだけだが
　　　**役割と用途がぶれると引数の扱いも変わりかねない**。
　　　だから役割と用途を事前に打ち出すのが大事なんだ。」

新人「承知しました！」

###### 第十一条 五項：サブルーチン作成後に引数と戻り値の様式が変わる事のないよう、事前に打ち出した役割と用途に対して適切なサブルーチンの作用を意識してサブルーチンの初期構築を行う。

遣付「**作用**の話が出たので`@_`の補足をしておこう。
　　　`@_`というよりかは`$_`を使わない方がいい理由だね。」

```perl:test45.pl
sub sample{
    $_[0] = 5;
}

my $param = 2;
sample($param);

print $param;
```

```text:出力結果
5
```

新人「うわ！元値が変わっちゃいました。」

遣付「そうなんだ。`@_`をレキシカル変数に代入する事無く
　　　**ダイレクトに代入をしてしまうとそのまま反映されてしまう**んだ。

>
配列 @_ は local 配列ですが、その要素は実際の スカラパラメータの別名です。 たとえば **$_[0] が更新された場合、対応する引数が更新されます** (更新できない場合にはエラーとなります)。
[perlsub - Perl のサブルーチン - 説明](https://perldoc.jp/docs/perl/5.26.1/perlsub.pod#DESCRIPTION)
>

新人「これは予期せぬ作用になりかねないからダメですね。」

遣付「まぁ第十条でも謳っているし、あくまで補足という事で。
　　　よし。じゃあ`return`については理解が得られたと思うので
　　　`die`の説明をしていこう。」

新人「そういや`return`か`die`でキメようという題目でしたね。
　　　お願いします。」

遣付「コンパイルが通っていれば動くような単純なサブルーチンであればよいが
　　　例えば、DBにコネクションを貼る、Webサービスを呼び出してJSONを得る、
　　　前に出たファイルオープンの話もそうだね。
　　　**実行時エラーが想定されるサブルーチン**というのも普通に考えられる。」

新人「そうですね。」

遣付「そういう場合は正常時の`return`とは別に`die`を書いておくのが無難だ。」

```perl:test46.pl
sub sample{
    my $sample_ret = 0;
    my $error = 0;
    #
    # （処理中略）
    #

    # 例外時
    if($error){
        die "Error occured."
    }

    return $sample_ret;
}

#
# （処理中略）
#

my $ret = 0;
eval{
    $ret = sample();
};
if($@){
    # 例外処理
}
```

遣付「`$@`にはエラーメッセージが入る。
　　　慣れない内は`eval`ブロック～`if($@)`までを
　　　イディオムとして捉えておけばいいだろう。」

>
構文エラーや実行エラーが発生するか、die 文が実行されると、 eval はスカラコンテキストでは undef が、 リストコンテキストでは空リストが設定され、 **\$@ にエラーメッセージが設定されます。** (5.16 以前では、バグによって、リストコンテキストで構文エラーの時には undef を返していましたが、実行エラーの時には 返していませんでした。) **エラーがなければ、$@ は空文字列に設定されます。**
[perlfunc - eval](https://perldoc.jp/func/eval)
>

新人「了解です！」

###### 第十一条 六項：実行時エラーが想定されるサブルーチンであれば`return`とは別に`die`を記述する。（合わせて、呼び出し元では`eval`ブロックを適用し`die`での戻り値がないか評価する事。）

遣付「よし。じゃあ締めに向かおう。」
　

#### 第十二条：サブルーチンのI/F定義は（最低限）コメントを必ず残そう。

遣付「本来であればサブルーチンの
　　　InputとOutputを整理した**設計書**を用意するのがよいのだが…」

新人「そんな時間はないですね…」

遣付「であれば**最低限コメントは残す**ようにしよう。
　　　例えば君がさっき作ったサブルーチンだな。」

```perl:test44_sinjin.pl
# 追加する対象を返却するサブルーチン
sub get_additive_for_hash_a{
    my $ref_hash_a = shift;
    #
    # （処理中略）
    #
    return \%ret;
}
```

遣付「最初と最後だけ見れば
　　　何か引数を一つ受け取って
　　　ハッシュのリファレンスを`return`しているのはわかるが
　　　**肝心の、サブルーチンが中で何をしているか？がわからない**。
　　　`return`が最後だけとは限らないし
　　　途中で`die`しているかもしれない。」

新人「確かに。」

遣付「なので、最低限必要なのは以下の通りだ。」

- 引数（型、数）
- 戻り値（型、数）
- サブルーチンの中で何をしているかの**概要**
- 実行時エラーケース（どういう場合に`die`するか）

新人「なるほど。**コメントの体裁は気にした方がいい**ですか？」

遣付「うん。サブルーチンのコメントの書き方として
　　　標準化されている形がベストだが最初はそこまで気にしなくてもいいだろう。
　　　**自分の建て付けた役割と用途を謳う**事、つまり
　　　**第三者に全てのソースコードを読ませないようにする**のが目的だからね。
　　　後になって、自分の建て付けを振り返れるという点も大きい。」

新人「ふむふむ。やってみます！」

```perl:test44_sinjin_with_comment.pl
# 追加する対象を返却するサブルーチン
#
# 引数：ハッシュAのリファレンス
# 戻り値：ハッシュAに追加する対象のハッシュリファレンス。
# 概要：ハッシュAとハッシュBを突合し、要件に従いハッシュAに追加するべきハッシュを生成する。
# 実行時エラー：特になし
sub get_additive_for_hash_a{
    my $ref_hash_a = shift;
    #
    # （処理中略）
    #
    return \%ret;
}
```

遣付「どうだ？
　　　これだけの情報でも**あるとないとでは変わる**だろう？」

新人「はい！」

遣付「後は必要に応じてサブルーチンのコメントの書き方も揃えていくと
　　　プロジェクト全体のソースコードがグッと読み易くなると思うよ。」

新人「わかりました！」

遣付「いよいよ最後だ。」
　

#### 第十三条：無闇に小難しい概念を取り入れるのはやめよう。（やるなら慎重に）

遣付「**ネットの情報を鵜呑みにしたらダメだ。**」

新人「どうしたんですか？いきなり。」

遣付「いや。はやる気持ちを抑えきれなくてな。」

新人「はぁ。」

遣付「これまでに様々な標準化を施してきた。全部振り返ってみよう。」

#### 第一条：まず「記号」に悩んだらPerldocを見よう。
###### 第一条 一項：記号で困ったらとりあえずPerldocを見る。
###### 第一条 二項：スクリプトを書く際は`strict`プラグマと`warnings`プラグマを必ず使用する。
`use strict;`
`use warnings;`
#### 第二条：演算子にまつわる書き方を統一しよう。
###### 第二条 一項：論理否定演算子`!`の後にはスペースを一つ置く。
###### 第二条 二項：論理否定演算子`not`は使わない。
###### 第二条 三項：ハッシュのキー・バリューはファットコンマ（=>）でつなぐ。（初期化時）
#### 第三条：構文糖（糖衣構文）はほどほどに。使うなら統一しよう。
###### 第三条 一項（改訂）：ハッシュの初期化子において、キーはクォートしない。キーを動的にしたい場合はハッシュを初期化したあとに行う
###### 第三条 二項：アロー演算子やデリファレンス修飾子は（できるだけ）省略しないで書く。
#### 第四条：制御文（条件分岐）はifもしくはunlessとorだけでいい。
###### 第四条 一項：条件分岐には基本的にif文を使用する。
###### 第四条 二項：unless文は文修飾子でのみ使用する。
###### 第四条 三項：or文はファイルのopenイディオムでのみ使用する。
###### 第四条 四項：条件演算子（三項演算子）はもし使うならシンプルに。
#### 第五条：制御文（ループ）はforかwhileでいい。
###### 第五条 一項：foreachは使わない。
###### 第五条 二項：for文のVARは省略しないで必ずmyをつける。
###### 第五条 三項：untilは使わない。
###### 第五条 四項：do whileは使わない。
###### 第五条 五項：while eachイディオムは使わない。（改訂の余地あり）
###### 第五条 六項：ループを実現する際はfor文かwhile文を使用する。（冗長記載だけど明記しておく）
###### 第五条 七項：無限ループを実装する場合は、ループ終了条件が収束するように確実に設計する。（具体策は別途、考えよう）
###### 第五条 八項：ループ制御文はnextとlastのみを使用し、redoとcontinueは使わない。
#### 第六条：文字列の取り扱いを決めよう。
###### 第六条 一項：文字列変数のみを引用する場合は変数展開`${}`を使用する。
###### 第六条 二項：文字列変数に加えて関数を引用する場合は変数展開と合わせて、文字列連結演算子`.`を使用する。
###### 第六条 三項：変数展開を行う際に、見通しがよくなるのであれば冗長であっても`${}`を使う。
###### 第六条 四項：ハッシュの代入において、キー値に変数展開を用いてもよいが、見づらくなるようであれば、キー値用のスカラ変数を別途用意する。
###### 第六条 五項：クォート風演算子は使わない。（暫定）
#### 第七条：変数名は確実に命名しよう。
###### 第七条 一項：同じ変数名を使わない。
###### 第七条 二項：一文字の変数は使わない。
#### 第八条：関数とサブルーチンの棲み分けをしておこう。
###### 第八条 一項：自分で作成した関数を『サブルーチン』と呼称する。
###### 第八条 二項：perlfuncで規定されるAPI関数、およびモジュールないしサードパーティ製のライブラリで提供される関数を『関数』と呼称する。
#### 第九条：サブルーチンの役割と用途は事前に打ち出そう。
###### 第九条 一項：既に存在するサブルーチンは作らない。
###### 第九条 二項：既に存在する関数ないしサブルーチンであっても、役割と用途を改善・拡張する形であれば、あらたにサブルーチンを作ってもよい。
#### 第十条：サブルーチンの引数はわかりやすくそしてシンプルに。
###### 第十条 一項：サブルーチンの呼び出し時はカッコを付ける。`subroutine(PARAM)`
###### 第十条 二項：サブルーチンプロトタイプは使わない。
###### 第十条 三項：単純にリスト値として渡せる引数（配列、ハッシュ）はそのままレキシカル変数にリスト代入する。
###### 第十条 四項：配列やハッシュを複数、引数として渡したい場合はリファレンスを使う。
###### 第十条 五項：引数がスカラ変数一つの場合は`@_`を省略し、`shift`関数で受ける。
#### 第十一条：サブルーチンの戻り値はreturnかdieでキメよう。
###### 第十一条 一項：戻り値のないサブルーチンは`return;`を最低限必ず書く。
###### 第十一条 二項：`return;`でしか戻さないサブルーチンの戻り値をレキシカル変数で受けない。
###### 第十一条 三項：サブルーチンの戻り値は（できるだけ）スカラで返す。
###### 第十一条 四項：やむを得ずリストの戻り値を定義したい場合は、スカラのリストとする。
###### 第十一条 五項：サブルーチン作成後に引数と戻り値の様式が変わる事のないよう、事前に打ち出した役割と用途に対して適切なサブルーチンの作用を意識してサブルーチンの初期構築を行う。
###### 第十一条 六項：実行時エラーが想定されるサブルーチンであれば`return`とは別に`die`を記述する。（合わせて、呼び出し元では`eval`ブロックを適用し`die`での戻り値がないか評価する事。）
#### 第十二条：サブルーチンのI/F定義は（最低限）コメントを必ず残そう。
#### 第十三条：無闇に小難しい概念を取り入れるのはやめよう。（やるなら慎重に）

新人「うわぁ。書くも書いたり、という感じですね。」

遣付「だが、これで終わりじゃないぞ。
　　　例えば第五条で出てきた`while～each`イディオムや
　　　第六条で出てきたクォート風演算子や単語リスト演算子など
　　　標準化を先送りにしたものもあるしね。」

新人「そうですね。」

遣付「なので最後の条では**新規に標準化として建て付ける際の注意点**を
　　　挙げておこう。
　　　まぁ、題目通りだけどね。」

新人「下手にしゃらくさい事はすんなという
　　　強いメッセージ性だけは感じます。」

遣付「なかなか勘がいいな。
　　　じゃあもういいか。」

新人「いえ。
　　　もうだいぶお疲れでしょうが
　　　簡単に説明をお願いします。」

遣付「わかった。がんばろう。
　　　Perl言語の初出は[Wikipedia](https://ja.wikipedia.org/wiki/Perl#%E6%AD%B4%E5%8F%B2)によると
　　　はるか昔**1987年**の事だ。
　　　Perl5だと**1994年**だね。
　　　そんな長い歴史が一言で語られるべくもなく
　　　Perlの文献はとても多い。
　　　書物もさることながらネット上の文献もだね。
　　　で、現場でよく目にするのは
　　　どちらかというとネットの文献ではないかな。」

新人「そうですね。
　　　本も一応手元には置いていますが
　　　作業の合間だと手軽なので
　　　ついついネットを参照する事の方が多いです。」

遣付「そこで冒頭の言葉だ。
　　　ネットの文献を鵜呑みにしてはいけない。
　　　記事によっては**Perlのバージョンが明記されていなかったり**
　　　やたら**マニアックなものをこねくり回したり**…と。」

新人「あー。何となくわかります。」

遣付「ただ勘違いしないで欲しい。
　　　全ての文献は著者にとっては間違いなく有用なものだ。
　　　**決して下手に考えなしにdisってはいけない。**
　　　大事な事は**ただ一つの客観的な事実**。
　　　『他人の文献で謳われている利便性はその人にとってのものであり
　　　　**この現場にとって有用とは限らない**』という事実だ。」

新人「なるほど。
　　　じゃあPerldocを見れば確実って事ですね！」

遣付「いや、Perldocも鵜呑みにしてはダメだ。」

新人「えぇ！？」

遣付「便利そうだなぁと思って
　　　よくよくPerldocを読んだら
　　　『はい。これは実験的なAPIでした～。』と
　　　**残念でした～**と言わんばかりの記述も中にはある。
　　　無論、実験的なAPIや未成熟なAPIが全てダメなわけではない。
　　　が、実験台にされるリスクと商用バグは天秤で計れないものだろう。」

新人「まぁ、そうですけど…
　　　じゃあ、わかりました！
　　　ここは**書籍**でs」

遣付「**Noだ**。」

新人「食い気味！」

遣付「例えば有名なPerl本として
　　　[Perlベストプラクティス](https://www.oreilly.co.jp/books/4873113008/)という本がある。
　　　でも[ベストじゃなくない？](https://songmu.jp/riji/entry/2014-07-24-pbp.html)と言っている人もいる。
　　　まぁこれは個人の価値観によるかもだけど。
　　　ただ、さっきも言った通りPerlの歴史は長い。
　　　その時代時代で最善とされてきた慣習が今ベストであるという確証はないんだ。」

新人「じゃあ、どうすれば…」

遣付「答えは簡単。
　　　**自分で手を動かして試してみる**事さ。」

新人「手を動かす…」

遣付「そう。
　　　『これは便利だよ！』と謳っているTipsを鵜呑みにして
　　　**いずれ商用として運用されるかもしれないソースコードに**
　　　**いきなりTipsの切れ端を書き始めるのは愚策**だ。
　　　標準化の観点からしてもよろしくない。」

新人「**標準化されていないものは書いてはいけない**という事ですね。」

遣付「それだと**語弊**があるかもしれない。
　　　標準化は確かにルールではあるが、
　　　**例外を絶対に認めないという事ではない**。
　　　標準化に縛られ過ぎてどう書けばよいのかわからなくなるのは**本末転倒**だし
　　　後追いで標準化していくというケースも当然、出てくるだろう。」

新人「ふむふむ。」

遣付「問題はそう、**Tipsのコピペ**という点なんだ。
　　　それだと既存ソースからのコピペと何も変わらなくなってしまう。
　　　だから良さげな文献を見つけて
　　　自分のソースコード構築にもメリットがありそうなのであれば
　　　きちんと**検証ソースを別に用意**して、
　　　**自分で手を動かして、自分の目で良し悪しを判断しろ**という事だ。」

新人「なるほど！
　　　それが**現場にとって有用とは限らない**というポイントですね！」

遣付「その通り。
　　　**現場に従事している人間が標準化を建て付ける事に意味がある**んだ。
　　　逆に言えば、現場にいない人間が標準化を建て付けたとしても
　　　それは**ただの理想論で終わってしまう**可能性もある。
　　　何が有用で、何を不要とするのか、
　　　それは現場の文化にも左右されるし
　　　ユーザによっても、納期によっても、
　　　はたまたジョインしているエンジニア達のスキルセットによっても
　　　変わってくるだろう。」

新人「ですねー。
　　　でも、**有用かどうか**って乱暴に言うと
　　　**さじ加減**だと思うんですが
　　　どういう風にその境目を見極めていけばよいですかね？」

遣付「そうだね。
　　　難しいところだけど…。
　　　例えば、これまでロクに触れていないPerlの大きな武器である**正規表現**だが、
　　　この先必ず標準化が必要になるだろう。
　　　これくらいならまだいい。
　　　既存ソースでも正規表現はたくさん使っているだろうから
　　　振り返りや過去の知見のマージという形でも標準化が可能だ。」

新人「はい。イケそうです。」

遣付「ただ、ここの既存ソースコードで１ミリも使われていないような概念、
　　　例えば[オブジェクト指向プログラミング（OOP）](https://perldoc.jp/docs/perl/5.14.1/perltoot.pod)とかだね。
　　　こいつを『あぁ便利そうだ。早速やってみよう。』と
　　　気軽に標準化するのは果たして効率的なのか？という疑問が残る。」

新人「うーん。確かに無理に使うのは厳しいかもですね。」

遣付「あとは名前空間である**パッケージ**を始めとした
　　　**シンボルテーブル**や**型グロブ**なども説明していないな。
　　　ただ、この先は標準化のメリットが大きくなってくるかもしれない。
　　　これ以外にもまだまだ有用に働くかもしれないものは色々あるぞ。」

新人「ふむふむ。
　　　とりあえず情報を集める事自体は悪い事ではないと判断しました。
　　　有用かどうかを自分で試して判断する為にも。」

遣付「アンテナ張りすぎてもアレなので、あとは時間と相談だね。」

新人「ですねー。」

遣付「…ところで、どうかな？
　　　ここまでだけでも得られた事は**Perlに特化した内容だろうか？**」

新人「いえ。考えを改められた気がします。」

遣付「Tipsを自分で検証する事ができた、そこから標準化を建て付けられた。
　　　もうその知見だけで**武器**なんだ。
　　　武器の種類と数を増やすことも、時には捨てることもできる。
　　　そして存分にその武器を振るう事に何のお咎めがあろうか。
　　　当初の君がなりたいイメージに少しでも近づけたと思うが如何かな？」

新人「はい！ありがとうございます！」

遣付「よかったよかった。
　　　ふぅ。なんだかんだで一日費やしてしまったな。
　　　明日からガンガンいこう！」

新人「よーし！やるぞー！」

# 冒険の終わりに

～～小粋なBGMが流れる、とあるBAR～～

陰照「**はぁ…そんな事があったんですね…**」

遣付「あぁ。」

新人「でもちゃんとバージョン１５３２はやり切りましたよ！陰照先輩！」

陰照「それは何よりです。
　　　それにしても**標準化**ですか…考えた事もなかったですね。」

遣付「まぁ詳しくは現場に戻ってから標準化仕様書を見てみてくれ。
　　　書き殴りもいい所だが、なかなかのモノに仕上がったぞ。」

新人「自分も加筆してます！フフン！（得意げ）
　　　ともあれ、リリースも無事に終わった！
　　　陰照先輩も無事に退院できた！
　　　めでたい！
　　　乾杯しましょう！カンパイ！」

チーン

遣付「何回カンパイするんだよ（笑）」

陰照「いやはや…その節はお二方には大変迷惑をかけてしまい…」

遣付「お前も何回謝るんだよ…そんな奴には**こう**だ！」

ペタッ

陰照「うわっ！何するんですか？」

新人「出た！遣付先輩の**おでこに付箋**攻撃だ！」

陰照「…何ですか？コレは。」

新人「覚えが悪いとおでこに標準化の内容だったり
　　　ありがたいお言葉が書かれた付箋を貼られるんです。」

陰照「えぇ…何その風習…コワい」

新人「私も一時期、貼られ過ぎて**のれんみたい**になってました！」

陰照「それはやり過ぎかと。」

遣付「まぁ半分冗談だ。
　　　陰照も何かあった時はそれを見てくれ。
　　　励みになればいいのだが。」

陰照「はい…ってアレ？店のBGMが急に止みましたね。」

遣付「…っと、そろそろか。」

新人「そうみたいですね。名残惜しいですが。」

陰照「え？まだ、飲み始めたばかりじゃないですか。」

遣付「陰照、がんばれよ。」

新人「陰照先輩！また会いましょう！」

陰照「え？え？どういう事…」

（暗転）

# エピローグ

？？？「…陰照君…陰照君！？」

陰照「（zzz）ハッ…はい！」

？？？「進捗会議中に**居眠り**とはいい度胸だねぇチミィ…！」

リーダー「申し訳ございません！！マネージャー殿！
　　　　　陰照は…その…申し上げにくいのですが
　　　　　**２０連勤中、かつ３徹目**でして…」

Ｍｇｒ「２０連勤～？３徹～？
　　　　そんな言い訳が通るわけないだろう！**軟弱**な！」

リーダー「ははぁ！申し訳ございません！申し訳ございません！」

（ペコペコ）

（ガミガミ）

Ｍｇｒ「それに何だね！
　　　　この陰照という男が課題管理表に挙げた内容は！
　　　　チミィ！読み上げてみたまえ！」　　　　

リーダー「えっと…**Perlコードとして何をどう書けば正解なのかがわからない**ですね…」

Ｍｇｒ「素人かね！」

会議参加者A（荒くれもののPerler）
　　　「オイオイ！冗談は程々にしとけよ！
　　　　そんなんでPerl開発ができると思ってんのかよ！オォン？」

会議参加者B（モヒカンのPerler）
　　　「ヒャッハー！そんなんじゃロクにコンパイルも通さねぇぜぇ…？」

会議参加者C（トゲトゲ肩パッドのPerler）
　　　「汚物は消毒だ～～～！」

会議参加者D（バギーに乗ったPerler）
　　　「土下座するなら許してやってもいいぜぇ！」

リーダー「申し訳ございません！申し訳ございません！
　　　　　幾分まだPerlを始めたてなものですから…！
　　　　　何とか…何とか挽回させますんで！」

（ザワザワ）

（ガヤガヤ）

陰照「（そうか…僕は進捗会議中に居眠りをしてしまったのか…）」

陰照「（何が**Perlを愛し、Perlに愛された男**だ。
　　　　僕は何て恥ずかしい**白昼夢**を…）」

Ｍｇｒ「えぇい！リーダー！
　　　　貴様の白々しい釈明はもういい！」

リーダー「申し訳ございません！申し訳ご…ガハァッ！（吐血）」

Ｍｇｒ「陰照とかいったな、この居眠り男が！
　　　　居眠りだけじゃなく、なんだ？
　　　　その**おでこに貼っ付けている**のは？！
　　　　ふざけているのかね？！」

（ヒラヒラ）

陰照「（これは…遣付先輩の…？）」

>
**Almost nothing in Perl serves a single purpose.**
**（PerlのAPIはほぼ例外なく複数の目的をかなえる。）**
　　　　　　　　　　　　　　　　　　　Larry Wall. 1997
>

陰照「（遣付先輩…！！）」

Ｍｇｒ「チミィ！聞いているのかね！？
　　　　この不始末、進捗の遅れ、どうしてくれるのかね！
　　　　どうやって取り戻すというのだね！？」

（バァン！！）

一同「ビクゥッッッ！！！」

Ｍｇｒ「な、何だ！？
　　　　急に机を叩いて立ち上がって…！
　　　　言いたい事があるなら言ってみたまえ！！」

陰照「…私が」

リーダー「陰照君…」

陰照「いえ、**我々**が最優先でやらなければいけない事。それは…」

一同「（ゴクリ）」

陰照「**標準化です。**」

～～Ｆｉｎ～～

# おわりに

著者がPerlで最初に作ったのは例に漏れずCGIでした。

今でいう[調整さん](https://chouseisan.com/)のようなWebシステム、
それをDBの代わりにCSVファイルを使ったり
無駄に正規表現を駆使したり
無駄に独自ドメインを取得したりして
キャッキャウフフしながら一人で悦に入っておりました。
無論、プライベートな遊びで、です。

その頃は**言語仕様？知るか。動きゃいいんだろボケが**という感じで
Perlと戯れていましたが、それから幾星霜を経て
まさか現場でPerlを触る事になるとは夢にも思いませんでした。
悪い意味で。

Perlの書き方なんか覚えているはずもありませんし
ちゃんと勉強しておけばよかったと思ったのは言うまでもありません。

**Perlを作ってて楽しかったのは確か。**
その思いだけを頼りに現場でPerlに取り組みましたが
**アゴか何かでタイピングしたのかな？**と思うような
既存のPerlプログラムが及ぼす精神汚染は筆舌に尽くしがたく
心を折られるのはそう遅くはありませんでした。

逆に言えば、汚いソースだったからこそ
**腹を括って**Perlをもう一度勉強するきっかけになった
と思えば**必要悪**だったのかな？とも思いますし
いや、やっぱりそのアゴ割ってやろうか？とも思います。
勉強にはなったので結果オーライです。（ニッコリ）

言語の流行り廃りはあまり関係なく
超レガシーな言語であっても
オワコンと後ろ指を指される言語であっても
そこから得られるものは少なからず必ずある
と筆者は思っていますが
それを時間の無駄と思うかどうかは個人の考え方次第です。

ただネットの情報に左右されずに
自分の**目**と**指**で確認していって欲しいとは思います。

長文乱文、失礼致しました。
ここまでご覧頂きありがとうございました。

# (Appendix1) Stack Overflow Developer Survey 2020

【2020/05/30追記】
脚注でも触れていますが、Stack Overflow Developer Survey 2020において
Perl言語が**高給ランキングのトップ**に入ったようです。またまたご冗談を！

厳密には**給与の中央値**のランキングなので
どこまで現実に即した数字なのかは微妙です。
が、調査結果の信憑性を差し引いても、なかなかに感慨深いですね。
あのPerl君がねぇ…大したもんだ。（偉そう）

リンクは[こちら](https://insights.stackoverflow.com/survey/2020#top-paying-technologies)。

原文
>
Globally, respondents who use Perl, Scala, and Go tend to have the highest salaries
, with a median salary around $75k. 
Interestingly, Perl is **amongst the top most dreaded languages**
, so it's possible that this high salary is to compensate for the dearth of developers who want to use that technology. 
When looking only at the US, Scala developers tend to have the highest salaries.
>

翻訳
>
世界的に見て、Perl、Scala、Goを使用している回答者の給与は最も高い傾向にあり、
給与の中央値は約75kドル（2020/05/29時点のレートでおよそ809万円）です。
興味深いことに、Perlは**最も嫌われている言語のトップに入っている**ので、
この高い給与は、その技術を使いたいと思う開発者の不足を補っている可能性があります。
アメリカだけを見ると、Scala の開発者の給料が最も高い傾向にあります。
>

そんなハッキリ言うなよ…（落涙）

でも、もしこのランキングがある程度の的を射た事実だとするなら
華々しい超最先端の技術と同様、技術者数の絶対的な不足、
要は「やれる人がいない」という状況が「高給」に繋がっているわけで
色々と思う所はありますね。
~~COBOLかな？~~

# (Appendix2) オンラインで学べて高い報酬が得られるプログラミング言語トップ15
【2020/06/16追記】
Business Insiderさんの記事「オンラインで学べて高い報酬が得られるプログラミング言語トップ15」にて
Perlがトップでした。
世界では何が起きているの…？

リンクは[こちら](https://www.businessinsider.jp/post-214571?mode=assets)。

[YAHOO!JAPANニュース](https://news.yahoo.co.jp/articles/aa4de4e1e8489872c9959697b1dba69c7ea0d6c1)にも載ったようです。

# (Appendix3) Perl7が満を持して登場
【2020/07/07追記】
Perlが四半世紀ぶりのメジャーバージョンアップを発表しました。

[Announcing Perl 7](https://www.perl.com/article/announcing-perl-7/)

ただ、発表しただけなので、実際のPerl7リリースは**まだまだ先**です。
RC版が出るまで早くとも半年、
できれば**来年2021年中に7.0としてユーザリリースしたい**との目論見のようです。

簡単なまとめを置いておきます。

### Perl7
現在の最新バージョンPerl5.32をベースとした新バージョンとなります。
Perl5.32ベースと言いつつ、ニュアンスとしては「ほぼ一緒」との事です。

>
Perl 7 is v5.32 with different settings. Your code should work if it’s not a mess.
（意訳：Perl7は異なる設定を伴うだけのPerl5.32。めんどいPerl5コードでなければPerl7でもほぼ動くよ。）
>

既存のPerl5対応CPANモジュールは基本的に動作する方向で進めているそうです。
また、Perl5からの移行性はそこまで低くはないとの事です。

```perl:例）Perl5のデフォルト動作を宣言するPerl7のプラグマ
use compat::perl5;  # act like Perl 5's defaults
```


ただ、肝心のPerl7としての目新しい機能は**ほぼない**みたいです。（えっ）

>
Q.What’s appearing?
A.Not much.
（意訳：何か新しいのある？いや、ねぇな。）
>

Perl言語の基盤として新たにPerl7（≒Perl5.32）を拡張していく指針なんだとは思いますが
現時点では、Perl5からPerl7への移行のメリットを
現実的に大きく打ち出すのは難しいかなぁとも思うので
Perl7のロードマップがもっと明確に宣言されて
各現場における既存の課題・問題を解決するに十分な根拠を見いだせるのであれば
移行するメリットは十分ありそうです。

果たして、Perlが再び覇権を取る日は訪れるのか…？

### Perl6
Perl6はPerl5に対する後方互換性を持たないので
**Perl5とはまったく別の言語**と言ってもよいでしょう。

Perl6は2015年に正式版がリリースされた割と新しめのPerlバージョニングです。

が、後方互換性をウリにしてきたPerl（Perl5）なのだから
このPerl6というバージョニングはおかしいのでは
とかねてより議論が繰り広げられていたようです。

そこで2019年の10月に「Raku」という名称に変更され
Perl6のサイトドメインも「perl6.org」から「raku.org」へと変わりました。

このRakuという命名はおそらく
Perl6コンパイラの「Rakudo」に由来するものと思われますが
Rakudoの[公式サイト](https://rakudo.org/)もぶっ飛んでいてなかなか面白いです。

>
"Rakudo" is short for "Rakuda-dō" (with a long 'o'; 駱駝道), which is Japanese for "Way of the Camel".
"Rakudo" (with a short 'o'; 楽土) also means "paradise" in Japanese.
（意訳：RakudoはRakuda-dōの略なんだ。日本語で言うと「ラクダの道」だね。
　また、オーを伸ばさないRakudo（楽土）は日本で「楽園」を意味するね。HAHAHA。）
※Rakudo公式のトップページにある鳥居の画像の上で数秒マウスオーバーすると、
　上記のイースターエッグが表示されます。
>

### Perl5
Perl7が出たらPerl5はお払い箱なのか…とお嘆きの皆さん。
安心してください。
Perl5は長期保守を目的としたLTM（Long Term Maintenance）モードに突入します。

>
What’s happening to Perl 5?
　
No one is taking Perl 5 away from you; 
it goes into long term maintenance mode—a lot longer than the two years of rolling support 
for the two latest user versions. 
That might be up to a decade from now (or half the time Perl 5 has already been around).
　
訳）
Perl5はどうなっちゃうの？
　
誰もあなたからPerl 5を奪うつもりはありません。
Perl5は、2つの最新のユーザバージョンの
2年間のローリングサポートよりもずっと長い長期メンテナンスモード（LTM）に入ります。
このLTMは今から10年続くかもしれませんし、
あるいは**Perl5がすでに存在している時間の半分**くらいは続いてしまうかもね！
>

Perl5が出て四半世紀。
まだまだPerl5は元気です。
あと10年はイケます。



[^1]: Stack OverflowのDeveloper Survey 2020（2020/02）にて、Perl言語はなんと高給ランキングのトップに輝きました！Business Insiderさんの記事「オンラインで学べて高い報酬が得られるプログラミング言語トップ15」（2020/06/16）でもトップの模様。稿末のAppendixに該当記事へのリンクと本文を載せています。