tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

【perl】perlのリスト(配列)を真面目に復習-初期化、リテラル、qwショートカット、index、個数、代入、foreach、コンテキスト、無名配列とかとか

はじめに

perl開発でリスト(配列)は良く使いますが
改めて初めてのPerl 第6版を読んだので初心に振り返ってリストを復習

初めてのPerl 第6版
初めてのPerl 第6版
posted with amazlet at 14.09.15
Randal L. Schwartz brian d foy Tom Phoenix
オライリージャパン
売り上げランキング: 23,310

ながれ

  1. リスト&配列とは
  2. 初期化
  3. リテラル
  4. qwショートカット
  5. index、個数
  6. 代入
  7. foreach
  8. コンテキスト
  9. 無名配列での良くある間違い例

1. リスト&配列とは

これはもうそのまんま引用です

リスト(list)とは、スカラーの集合に順序を付けて並べたもの
配列とは、リストを格納する変数

補足

この後からコードをいくつか載せますが、
めんどうなので最初にこれが書かれてる前提とします。

#! /usr/bin/perl

use strict;
use 5.010;

2. 初期化

配列の初期化についてです。
自分的なポイントだけまとめておきます

  • my @arr;で初期化した際はmy @arr = ();と同じ
  • スカラ変数に無名配列のリファレンスで代入することも可能(コードの$arr04)

ってことでコードで語る

my @arr01; # my @arr = ();と同じ
say @arr01; # 結果-> なにも表示されない

my @arr02 = ();
say @arr02; # 結果-> なにも表示されない

my @arr03 = (1,2,3);
say @arr03; # 結果-> 123

# スカラ変数に無名配列のリファレンスの形で代入することも可能
my $arr04 = [1,2,3,4];
say @$arr04; # 結果-> 1234

3. リテラル

次はリテラルについて。
初期化の形で右辺にリテラルを書くことでいくつか試します。
自分的なポイント

ってことでコードで

# 数値でのリテラル
my @arr01 = (1, 2, 3);
say @arr01; # 結果-> 123

# 文字列でのリテラル
my @arr02 = ('hoge', 'piyo', 'fuga');
say @arr02; # 結果-> hogepiyofuga

# 数値と文字列でのリテラル
my @arr03 = (1, 3, 5, 'hoge');
say @arr03; # 結果-> 135hoge

# カラ
my @arr04 = ();
say @arr04; # 結果-> なにも表示されない

# 範囲指定演算子
my @arr05 = (2..8);
say @arr05; # 結果-> 2345678

# 小数点を指定すると切り捨て
my @arr06 = (2.3..8.1);
say @arr06; # 結果-> 2345678

4. qwショートカット

んで今度はqwショートカットです
これ普通に使ってはいましたが、qwショートカットって言うんですね。呼び方を始めて知りましたw

自分的ポイント

  • 空白文字は無視される
  • デリミタは/!やカッコ系でもいい
  • 変数展開はされない

コード

# qwショートカット使って初期化例
my @arr01 = qw/hoge piyo fuga/;
say @arr01; # 結果-> hoge piyo fuga

# 空白文字は無視される
my @arr02 = qw/
hoge
piyo
fuga
/;
say @arr02; # 結果-> hoge piyo huga

# クオートでかこったやつもそのまま表示される
my @arr03 = qw/"hoge" "piyo" "fuga"/;
say @arr03; # 結果-> "hoge""piyo""fuga"

# デリミタ例
my @arr04 = qw! hoge piyo fuga!;
say @arr04; # 結果-> hogepiyofuga

my @arr05 = qw# hoge piyo fuga#;
say @arr05; # 結果-> hogepiyofuga

my @arr06 = qw(hoge piyo huga);
say @arr06; # 結果-> hogepiyofuga

# 変数展開はされない
my $str = 'unko';
my @arr07 = qw/hoge piyo fuga $str/;
say @arr07; # 結果-> hogepiyofuga$str

5. index、個数

配列のindex(要素へのアクセス)と個数についてです。

indexは0からみたいなことは他の言語と同様なので、
こちらも自分的ポイントだけ

  • 要素番号の小数点以下は切り捨て
  • 素数を超えてアクセスすると途中の要素がundefで初期化される
  • $#nameで最後の要素のインデックスが得られる
  • カラコンテキストで代入すると個数が得られる
# 普通に要素アクセスしてみる
my @arr01 = qw / hoge fuga piyo /;
say $arr01[0];
say $arr01[1];
say $arr01[2];


# 要素数を超えてアクセスすると途中の要素がundefで初期化される
$arr01[5] = 'tekitou';
my $i = 0;
foreach( @arr01 )
{
  say $i; # 結果-> 0〜5まで表示される
  $i++;
}

# `$#name`で最後の要素のインデックスが得られる
my $arr_num1 = $#arr01;
say $arr_num1; # 結果-> 5

# スカラコンテキストで代入すると個数が得られる
my $arr_num2 = @arr01;
say $arr_num2; # 結果-> 6

6. 代入

こちらはいきなりコードから

# スカラ値に代入する的にリスト値を変数に代入できる
my ($a, $b, $c) = ('hoge', 'fuga', 'piyo');
say $a; # 結果-> hoge
say $b; # 結果-> fuga
say $c; # 結果-> piyo

# 右辺が少ないときはundefで初期化される
my ($d, $e, $f) = ('hoge', 'fuga');
say $d; # 結果-> hoge
say $e; # 結果-> fuga
say $f; # 結果-> Use of uninitialized value $f

# 左辺が少ないときは捨てられる
my ($g, $h) = ('hoge', 'fuga', 'piyo');
say $g; # 結果-> hoge
say $h; # 結果-> fuga

# 複数の配列も代入できる
my @arr01 = (1, 2, 3);
my @arr02 = (4, 5);

my @arr03 = (@arr01, @arr02);
say @arr03; # 結果-> 12345

# カラの配列はシカトされる
my @arr04 = (1, 2, 3);
my @arr05 = ();
my @arr06 = (4, 5);

my @arr07 = (@arr04, @arr05, @arr06);
my $arr_num1 = @arr07;
say @arr07; # 結果-> 12345
say $arr_num1; # 結果-> 5 (6個ではない!)

# undefは明示的にセットできる
my @arr08 = (@arr04, undef, @arr06);
my $arr_num2 = @arr08;
say @arr08; # 結果-> 12345(Use of uninitialized value $arr08[3])
say $arr_num2; # 結果-> 6

7. foreach

リストそのものというよりは、
foreachでリストをループさせるときの制御変数について

自分的ポイント

  • ループ中の制御変数はリストの要素そのもの

コード

# 制御変数はリストの要素そのもの
my @arr = qw/hoge fuga piyo/;
foreach( @arr )
{
  $_ = $_ . 'dayo';
}
say @arr; # 結果-> hogedayofugadayopiyodayo

8. コンテキスト

最後にコンテキストについて。
初めてのPerl 第6版でもここが本書の中で最も重要なセクションと言ってるほどです。

コンテキストについては自分的ポイントよりコードのほうが良いので省きます(手抜きw)

コンテキストとは

式をどのように使うかを表す概念。
perlが式を解析する際には、必ずスカラー値かリスト値のどちらかを期待する。
※今回はスカラーとリストにしぼって説明

コンテキスト例

リストの個数を得る例で説明します。(5. index、個数の最後でも少し触れたやつ)

my @words = ('hoge', 'fuga', 'piyo');

# コンテキストの違い
my @list = @words; # リストコンテキスト
my $list_num = @words; # スカラコンテキスト

say @list; # 結果-> hogefugapiyo
say $list_num; # 結果-> 3

@listと$list_numを初期化しているところがコンテキストの違いです。
右辺が同じ@wordsですが、左辺の形によって式の解釈が変わっています。
コンテキストってこんな感じ。

カラコンテキスト

perlがスカラとして扱う式です。
わかりにくい説明より見た方が早いので例

my @words = ('hoge', 'fuga', 'piyo');

# 例
my $num = @words; # スカラコンテキスト
$words[3] = 'unko'; # スカラコンテキスト
if( $words[3] ){ }; # スカラコンテキスト
while( $words[4] ){}; # スカラコンテキスト

my ($any) = @words; # リストコンテキスト!
say $any; # 結果-> hoge

最後のmy ($any)だけリストコンテキストになります。
他はperlがスカラコンテキストとして解析するってことですね。

リストコンテキスト

こちらもいきなし例

# リストコンテキスト例
my @words = ('hoge', 'fuga', 'piyo'); # リストコンテキスト
my ($first, $second) = @words; # リストコンテキスト
push @words, 'unko'; # リストコンテキスト
foreach my $word ( @words ) { }; # リストコンテキスト

print $words[0]; # 密かにこれもリストコンテキスト
print "\n";

リストコンテキストはわかりやすいですね。 結構まんまです。

自分的に忘れがちになるのが、最後のprint $words[0];もリストコンテキストということですかね。

カラコンテキストの強制

擬似関数slacarを使うことでスカラを強制できますっていう例

my @words = ('hoge', 'fuga', 'piyo'); # リストコンテキスト

# カンマで複数出力
say "this words is : " , @words; # 結果-> this words is hogefugapiyo
say "this words is : " , scalar @words; # 結果-> this words is 3

# ドットで連結
say "this words is : " . @words; # 結果-> this words is 3

3つ目のsayのように.で文字列連結を期待する場合もスカラになります

9. 無名配列での良くある間違い例

こちらは初めてのPerl 第6版に書いてあるわけではないですが
良く見る間違い例です

配列をコピーや代入しようとして間違い

リストのというか無名配列のリファレンスの扱いについての間違いでです

my $words = ['hoge', 'fuga', 'piyo'];

# 間違い
my @any_words = $words;
say $any_words[0]; # 結果-> ARRAY(0x7fa088803ea0)

# 正解
my @any_words = @$words;
say $any_words[0]; # 結果-> hoge

アロー演算子(->)の有る無しでの間違い

こちらも無名配列とリストの取り扱いについてですね。

my $words = ['hoge', 'fuga', 'piyo'];
my @any_words = @$words;

# 間違い
say $words[0]; # 結果-> エラー(Global symbol "@words" requires...)

# 正解
say $words->[0]; # 結果-> hoge


# 間違い
say $any_words->[0]; # 結果-> エラー(Global symbol "$any_words" requires...)

# 正解
say $any_words[0]; # 結果-> hoge

これは実際にはエラーが出て実行できないので適宜直すかコメントして実行してみてください。

簡易的にまとめるとこんな感じですかね。

リスト(配列)は

  • my @arrで初期化
  • $arr[0]で要素取り出し

無名配列のリファレンスは

まとめ

ってことで、perlのリスト(配列)について復習してみました。

復習してみても知ってることばっかりなはずなのに
開発中は細かいことでミスってるのにあってるはずという思考のトラップで なんでうまくいかないなーと小一時間悩むときありますよね。

そんなときこそこういう初心の復習が大事だと思いました(><)

その他参考