htsign's blog

ノンジャンルで書くつもりだけど技術系が多いんじゃないかと思います

Perl の range operator

これPerlerの皆さまからすれば「何を今更」な話かもしれませんが、個人的に驚いたので書きます。

Perlには範囲演算子というのがあって、他の言語でも度々採用されてる便利な演算子なんですが、
例えば

my @nums = (1..5);

とすることで 1 から 5 までの連番を含む配列を定義できます。

単純な文字列なら、

my @strings = ("aa".."ae");
print "@strings\n";          #==> aa ab ac ad ae

とかもできますね。

さて、この2例目の("aa".."ae")みたいな文字列の範囲を配列にするにあたって、

# これは期待通り
my @arr1 = ("A".."Z"); #==> A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

# これも期待通り
my @arr2 = ("a".."z"); #==> a b c d e f g h i j k l m n o p q r s t u v w x y z

# じゃあこれは…?
my @arr3 = ("A".."z");

私は3つ目の出力はA B C ... X Y Z [ \ ] ^ _ ` a b c ... x y zとなると期待しました。
なぜなら私の知る他の言語では同じように組むとそういう結果になるからです。

でもPerlでは("A".."Z")と等価でした。
期待する結果を得るには

my @arr4 = map {chr} (ord "A"..ord "z");

とする必要があったようです。

理由について多少なり調べてみましたが、どうも納得のいく結論には達しませんでした。
「そういう仕様だから」ということで終わりにします。