続・はじめてのPerl 6章

6章 複雑なデータ構造の操作

6.1 デバッガを使って複雑なデータを見るには
デバッガの起動
    -dスイッチを指定してPerlを起動
        $ perl -d sample.pl

デバッガの使い方
    デバッガは、今から実行する行を出力しコマンド入力を待つ

    sコマンド
        プログラムのシングルステップ実行

    xコマンド
        指定したリストの値をダンプ
            値がハッシュリファレンスだった場合
                キーと値のペアが分かるように出力される
            値が配列だった場合
                添字とともに値が出力される

        x sort keys %ref というような指定も可能

    qコマンド
        デバッガの終了

    hコマンド
        ヘルプの表示

デバッガそのほか
    リリース毎に動作が変わる
# sample.pl
my @array = (
    {
        name    =>  'tyamaguc07',
        skill   =>  [ qw/ C Perl JavaScript MySQL / ],
    },
    {
        name    =>  'brother',
        skill   =>  [ qw/ tennis swimming / ],
    },
);


for my $ref ( @array ) {
    my $name = $ref->{name};

    for my $skill ( @{ $ref->{skill} } ) {
        print "$name : $skill\n";
    }
}
上記のコードをデバッガを使って実行
$ perl -d sample.pl

Loading DB routines from perl5db.pl version 1.33
Editor support available.

Enter h or `h h' for help, or `perldoc perldebug' for more help.

main::(sample.pl:1):    my @array = (
main::(sample.pl:2):        {
main::(sample.pl:3):            name    =>  'tyamaguc07',
main::(sample.pl:4):            skill   =>  [ qw/ C Perl JavaScript MySQL / ],

  DB<1> s
main::(sample.pl:13):   for my $ref ( @array ) {

  DB<1> x @array
0  HASH(0xa38e8c)
   'name' => 'tyamaguc07'
   'skill' => ARRAY(0xa38eec)
      0  'C'
      1  'Perl'
      2  'JavaScript'
      3  'MySQL'
1  HASH(0xb14d04)
   'name' => 'brother'
   'skill' => ARRAY(0xcd0a14)
      0  'tennis'
      1  'swimming'

  DB<2> s
main::(sample.pl:14):       my $name = $ref->{name};

  DB<2> x sort keys %$ref
0  'name'
1  'skill'

  DB<3> s
main::(sample.pl:16):       for my $skill ( @{ $ref->{skill} } ) {

  DB<3> s
main::(sample.pl:16):       for my $skill ( @{ $ref->{skill} } ) {

  DB<3> x $name, $skill
0  'tyamaguc07'
1  undef

  DB<4> q

$
6.2 Data::Dumperを使った複雑なデータの表示
Data::Dumper
    Perlのコアモジュール
    優れた、ダンプパッケージ

    Dumperサブルーチン
        1つ以上の値を与えると、表示可能な文字列に変換される
            デバッガのxコマンドと似ている

        Dumperが生成する文字列はPerlコード
            生成された文字列を評価することで、元のデータと同じデータが得られる

    共有データを適切に処理
        例えば、循環参照しているデータ
use Data::Dumper;

my @array = (
    {
        name    =>  'tyamaguc07',
        skill   =>  [ qw/ C Perl JavaScript MySQL / ],
    },
    {
        name    =>  'brother',
        skill   =>  [ qw/ tennis swimming / ],
    },
);
print Dumper \@array;
=pod 以下のように出力される
$VAR1 = [
          {
            'skill' => [
                         'C',
                         'Perl',
                         'JavaScript',
                         'MySQL'
                       ],
            'name' => 'tyamaguc07'
          },
          {
            'skill' => [
                         'tennis',
                         'swimming'
                       ],
            'name' => 'brother'
          }
        ];
use Data::Dumper;

$Data::Dumper::Purity = 1;  # 循環参照しているデータがあるかもしれないことを宣言

my @data1 = qw/ a b c /;
my @data2 = qw/ 1 2 /;
push @data1, \@data2;
push @data2, \@data1;

print Dumper \@data1, \@data2;
=pod 以下のように出力される
$VAR1 = [
          'a',
          'b',
          'c',
          [
            '1',
            '2',
            []
          ]
        ];
$VAR1->[3][2] = $VAR1;
$VAR2 = $VAR1->[3];
6.3 YAML
YAML
    Yet Another Markup Language

    Data::Dumperより読みやすく、コンパクトなダンプモジュール
use YAML;

my @array = (
    {
        name    =>  'tyamaguc07',
        skill   =>  [ qw/ C Perl JavaScript MySQL / ],
    },
    {
        name    =>  'brother',
        skill   =>  [ qw/ tennis swimming / ],
    },
);

print Dump( \@array );

=pod 以下のように出力される
---
- name: tyamaguc07
  skill:
    - C
    - Perl
    - JavaScript
    - MySQL
- name: brother
  skill:
    - tennis
    - swimming
6.4 Storableで複雑なデータを格納するには
マーシャリング
    データをバイトストリームとしてファイルに書き込める形式に変換し、後で作り直せるようにすること

Data::Dumperを使ったマーシャリング
    1. Dumperルーチンの出力内容をファイル出力
    2. 他のプログラムで、そのファイルを読み込み
    3. ファイル内の文字列をPerlのコードとして評価
    4. 元のデータと同じデータを持つ、$VAR{\d+} というパッケージ変数を取得することができる

Storable
    Perlのコアモジュール(v5.7.3から)

    優れたマーシャリングモジュール
        Data::Dumperで生成するファイルに比べ、小さく、高速に処理できるファイルを生成できる

    インターフェイスは、Data::Dumperと似ている
# outputファイルに出力される
use Storable;

my @array = (
    {
        name    =>  'tyamaguc07',
        skill   =>  [ qw/ C Perl JavaScript MySQL / ],
    },
    {
        name    =>  'brother',
        skill   =>  [ qw/ tennis swimming / ],
    },
);

store [ \@array ], 'output';
# outputファイルから読み込み、Dumpする
use Storable;
use Data::Dumper;

my $result = retrieve 'output';
print Dumper $result;
=pod 以下のように出力される
$VAR1 = [
          [
            {
              'skill' => [
                           'C',
                           'Perl',
                           'JavaScript',
                           'MySQL'
                         ],
              'name' => 'tyamaguc07'
            },
            {
              'skill' => [
                           'tennis',
                           'swimming'
                         ],
              'name' => 'brother'
            }
          ]
        ];
6.5 map演算子grep演算子の使い方
複雑なデータ構造を処理するために、grepとmapを使えるようにしておくと役に立つ
6.6 間接指定のちょっとした応用
# 各桁の数の和が奇数になるアイテムの添字を取得する
my @numbers = qw/ 1 2 4 8 16 32 64 /;

my @result = grep {
    my $sum = ();
    $sum += $_ for split //, $numbers[$_];
    $sum % 2;
} 0 .. @numbers;

print "@result\n";  # 0 4 5

# 値が必要になった場合、スライスを使えば取得できる
my @result_numbers = @numbers[ @result ];
grep、mapで間接指定を活用するポイント
    $_にハッシュのキーや配列の添字のような識別氏を用い、
    ブロックや実施あの値にアクセスする式の中で使う

感想

デバッガの存在、知りませんでした。
あとは基本的に復習。


そして、7章を予習してみたが、
知らなかったことが多くとても面白かった。
明日また読むのが楽しみ。


続・初めてのPerl 改訂版

続・初めてのPerl 改訂版