Perlの多次元配列の初期化を1行で書いてみたけど、やめたほうがいい

いきなり結論

3次元配列を0初期化する場合。

@multi_array=map{[map{[map{0}(0..2)]}(0..4)]}(0..7); #multi_array[8][5][3]

でも、普通にこっちのほうがいいよ

my @array;
for my $i(0..7){
    for my $j(0..4){
        for my $k(0..2){
            $array[$i][$j][$k]=0;
        }
    }
}

やめたほうがいい理由

読みにくい、書きにくい

1行にmapが3回も出てきます。中括弧と角かっこのネストも多く、間違いやすいです。

素数がわかりにくい

作りたい配列の要素数は[8][5][3]ですが、コードは添え字の数字が逆の順に出てきます。コメントなど、何らかの追加情報がないと誤解を招きます。

これを書いた本人も、末尾コメントがなければ理解できる自信がないです。

ゼロ初期化以外が書きにくい(拡張性がない)

中に複雑な初期値を書くことができません、少なくともif文を追加するのは向きません。 一から書いた、初版のプログラムでは、全ての要素は初期値ゼロでいいかもしれません。しかし、プログラムに機能を追加・拡張していくと、「偶数行だけ別の値にしたい」「規則的な値を入れたい」となることは時々あります。この初期化の後にfor文で追加の初期化を書けばよいかもしれませんが、(結果論では)最初からfor文で書いておいたほうがシンプルです。

よく考えると利用機会が限られる

3次元配列って必要でしょうか。多数のデータ、複雑な構造を持つデータなら、オブジェクトの配列や、あるいはデータベースで表したほうが有利なことはないか、考える余地はあります。これはプログラムの文法というより、構成や設計寄りの検討になります。

数学の3次元行列そのものを扱うときには必要なので、要は適材適所、です。

最後に

短く書くことはプログラマの美徳なこともありますが「短く『簡潔』」であることも重要だと思います。また、あまり省略しすぎると追記(拡張)に耐えられないこともあります。

短くて難しい記述は長くて読みやすい記述とトレードオフとも言えるので、凝った記述に凝りすぎないようにしましょう。なにごともほどほどに。

付録:いちおう解説

普通に書いた場合(再掲)。

my @array;
for my $i(0..7){
    for my $j(0..4){
        for my $k(0..2){
            $array[$i][$j][$k]=0;
        }
    }
}

ところで、formapについて、次の2つの式は同じ結果になります。

for my $i (0..9){$array[$i]=0;}
@array=map{0](0..9); #same

それを使い、一番内側のformapにします。

for my $i(0..7){
    for my $j(0..4){
            $array[$i][$j]=map{0}(0..2); #(0,0,0)のリスト
    }
}

同じように2次元目も。2次元配列=リファレンスの配列なので、mapの結果に角括弧をつけ、配列のリファレンスとして返します。

for my $i(0..7){
    $array[$i]=map{[map{0}(0..2)]}(0..4); #[0,0,0]のリファレンス×5。
}

あと一息。

@array=map{[map{[map{0}(0..2)]}(0..4)]}(0..7);

おしまい。