7. What Does Your Code Smell Like?
• strand sort を行うプログラム
• Perl5 のコードを Perl6 のコードへ
8. use 5.10.0; # for given/when
sub merge {
my ($x, $y) = @_;
my @out;
while (@$x and @$y) {
given ($x->[-1] <=> $y->[-1]) {
when( 1) { unshift @out, pop @$x }
when(-1) { unshift @out, pop @$y }
default { splice @out, 0, 0, pop(@$x), pop(@$y) }
}
}
return @$x, @$y, @out
}
sub strand {
my $x = shift;
my @out = shift @$x // return;
if (@$x) {
for (-@$x .. -1) {
if ($x->[$_] >= $out[-1]) {
push @out, splice @$x, $_, 1
}
}
}
return @out
}
sub strand_sort {
my @x = @_;
my @out;
while (my @strand = strand(@x)) {
@out = merge(@out, @strand)
}
@out
}
my @a = map (int rand(100), 1 .. 10);
say "Before @a";
@a = strand_sort(@a);
say "After @a";
9. sub infix:<M> (@x is rw, @y is rw) {
gather {
while @x and @y {
given @x[0] cmp @y[0] {
when Increase { take @x.shift }
when Decrease { take @y.shift }
when Same { take @x.shift, @y.shift }
}
}
take @x, @y
}
}
sub strand (@x is rw) {
my $prev = -Inf;
my $i = 0;
gather while $i < @x {
if @x[$i] before $prev {
$i++;
}
else {
take $prev = @x.splice($i, 1)[0];
}
}
}
sub strand_sort (@x is copy) {
my @out;
@out M= strand(@x) while @x;
@out
}
my @a = (^100).roll(10);
say "Before @a[]";
@a = strand_sort(@a);
say "After @a[]";
@a = <The quick brown fox jumps over the lazy dog>;
say "Before @a[]";
@a = strand_sort(@a);
say "After @a[]";
10. 今回のお話
• What Does Your Code Smell Like?
を元に Perl6 を紹介します
• (時間の都合で)全部は紹介しません
24. 見慣れないものたち
sub infix:<M> (@x is rw, @y is rw) {
gather {
while @x and @y {
given @x[0] cmp @y[0] {
when Increase { take @x.shift }
when Decrease { take @y.shift }
when Same { take @x.shift, @y.shift }
}
}
take @x, @y
}
}
28. こう定義して……
sub infix:<M> (@x is rw, @y is rw) {
gather {
while @x and @y {
given @x[0] cmp @y[0] {
when Increase { take @x.shift }
when Decrease { take @y.shift }
when Same { take @x.shift, @y.shift }
}
}
take @x, @y
}
}
32. is ***
• Perl6 では引数は読み取り専用
• 引数の値を変更したい場合は is rw
• 引数のコピーが欲しい場合は is copy
33. is rw を使うと
sub writable ($x is rw) {
$x += 1;
say "x = $x";
}
my $orig = 10;
say "orig = $orig";
writable($orig);
say "orig = $orig";
# orig = 10
# x = 11
# orig = 11
34. is copy を使うと
sub copy_value ($x is copy) {
$x += 1;
say "x = $x";
}
my $orig = 10;
say "orig = $orig";
copy_value($orig);
say "orig = $orig";
# orig = 10
# x = 11
# orig = 10
35. 何も指定しなかった場合
sub read_only ($x) {
$x += 1;
say "x = $x";
}
my $orig = 10;
say "orig = $orig";
read_only($orig);
say "orig = $orig";
# orig = 10
# Cannot assign to a readonly variable or a value
# in block at src/gen/CORE.setting:11981
# in sub read_only at is.pl:2
# in block at is.pl:8
37. gather ... take
• gather は遅延評価リストを返す
• 評価時に gather ブロック内を走査
• take された要素を見つけて返す
38. 簡単な例
my @list = gather {
for 0 .. Inf {
take $_ ** $_;
}
}
say @list[0..3]; # 1 1 4 27
39. merge関数での使い方
sub infix:<M> (@x is rw, @y is rw) {
gather {
while @x and @y {
given @x[0] cmp @y[0] {
when Increase { take @x.shift }
when Decrease { take @y.shift }
when Same { take @x.shift, @y.shift }
}
}
take @x, @y
}
}