2014/05/27(火)Perl Data Language 基礎編 #08 「データフロー」

データフローは、多数のピドルの間をデータが流れるようにするため、ピドル同士を結びつける概念です。たとえば、大きいデータ配列のピドルから部分的にデータを抜き出したピドルに変更を加えたりすると、その変更が元のピドルにも伝染します。

一般的にPDLの要素選択演算子(sliceやindex)は明白に切断しない限りデータフローコネクションが維持されます。データフローをサポートするため、PDLには2つの異なる代入方法があります。1つがグローバル代入演算子の「=」でもう1つが計算代入演算子の「.=」です。グローバル代入演算子は新しいピドルを作るのに使われ、計算代入演算子はすでに存在するピドルに値を挿入するのに使われます。

78行目でデータフローコネクションが作られないのは、「*」でコピーが生成されるためだと思います。混乱を避けるためには明示的にcopyメソッドを使うほうがいいかな。

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use PDL;
use PDL::NiceSlice;

my $a = pdl [ 1 .. 5 ];
say "$a $a";
print "\n";

say "グローバル代入";
my $b = $a(2); # スライスしたのをグローバル代入
$b++;

say "$a $a";
say "$b $b";
print "\n";

say "計算代入";
$b .= 100; # 計算代入

say "$a $a";
say "$b $b";
print "n";

say "スカラーではデータフローコネクションは維持されないことを確認";
for my $i ($a->listindices)
{
    my $tmp = $a->at($i);
    $tmp++;
}

for my $elem ($a->list)
{
    $elem++;
}

say "$a $a";
say "$b $b";
print "\n";

say "データフローコネクションの切断";
my $c = pdl [ 6 .. 10 ];

my $d = $c(2)->copy; # 物理コピー(コネクションは維持されない)
$d .= 555;

my $e = $c(2)->sever; # データフローコネクションの明示的な切断
$e .= 777;

say "$c $c";
say "$d $d";
say "$e $e";

my $f = $c->sever; # severはデータフローコネクションが作られていないものに対しては作用しない
$f += 100;
say "$c $c";
print "\n";

say "スライスしない場合のデータフローの確認";
my $g = pdl [ 1, 2, 3 ];
say "$g $g";

my $h = $g;
$h += 1000;
say "$g $g";
say "$h $h";

my $i = PDL->null;
$i .= $g;
$i += 1000;
say "$g $g";
say "$i $i";

my $k = pdl [ 8, 7, 3, 9 ];
my $l = $k * 2;
$l += 1000;
say "$k = $k";
say "$l = $l";

$k += 10;
say "$k = $k";
say "$l = $l";

実行結果↓

$a [1 2 3 4 5]

グローバル代入
$a [1 2 4 4 5]
$b [4]

計算代入
$a [1 2 100 4 5]
$b [100]

スカラーではデータフローコネクションは維持されないことを確認
$a [1 2 100 4 5]
$b [100]

データフローコネクションの切断
$c [6 7 8 9 10]
$d [555]
$e [777]
$c [106 107 108 109 110]

スライスしない場合のデータフローの確認
$g [1 2 3]
$g [1001 1002 1003]
$h [1001 1002 1003]
$g [1001 1002 1003]
$i [2001 2002 2003]
$k = [8 7 3 9]
$l = [1016 1014 1006 1018]
$k = [18 17 13 19]
$l = [1016 1014 1006 1018]