"what does your code smell like?"で学ぶperl6

Post on 03-Jul-2015

477 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

2012/10/19 at Yokohama.pm #9

TRANSCRIPT

"What Does Your Code Smell Like?"で学ぶPerl6

by risouat yokohama.pm #9

はじめに

• 今回は Perl6 のお話をします• Perl6 に興味のない方は、15分の休憩と思ってゆっくりしてください。

YAPCお疲れ様でした

•面白くてタメになるトークがたくさん

•懇親会の美味しい料理

• LTthonのすごい盛り上がり

• etc...

ところで

Larry のトーク聴きましたか?

What Does Your Code Smell Like?

• strand sort を行うプログラム

• Perl5 のコードを Perl6 のコードへ

use 5.10.0; # for given/whensub 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";

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[]";

今回のお話

• “What Does Your Code Smell Like?”を元に Perl6 を紹介します

•(時間の都合で)全部は紹介しません

文法の違い

merge関数

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 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 merge ($x, $y) {# 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 merge ($x, $y) {# 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 merge (@x, @y) {# 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}

strand関数

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 { 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 (@x) { my @out = shift @x // return; if @x { for -@x .. -1 { if (@x[$_] >= @out[-1]) { push @out, splice @x, $_, 1 } } } return @out}

配列の添字にマイナスは使えない

sub strand (@x) { my @out = shift @x // return; if @x { for -@x .. -1 { if (@x[*+$_] >= @out[*-1]) { push @out, splice @x, *+$_, 1 } } } return @out}

範囲指定時の ^

sub strand (@x) { my @out = shift @x // return; if @x { for 0 ..^ @x { if (@x[$_] >= @out[*-1]) { push @out, splice @x, $_, 1 } } } return @out}

変更点まとめ

• 引数の受取り方が変わった• if, while 等の条件指定時に括弧が不要• 全ての変数がリファレンスに• 配列の添字に負数は使えない→代わりに whatever(*) を使う

• 範囲指定の .. に ^ をつけると、その値を除外( 0 ^..^ 3 => 1, 2 )

見慣れないキーワード

見慣れないものたち

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 }}

infix:<M>

infix:<***>

•いわゆる中置演算子の定義

•引数を2つとる

sub infix:<exp> ($x, $y) { $x ** $y;}

say 3 exp 4; # 81

(例) べき乗の関数

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_sort (@x is copy) { my @out; @out = @out M strand(@x) while @x; @out;}

こう使う

sub strand_sort (@x is copy) { my @out; @out M= strand(@x) while @x; @out;}

こう書くこともできる

is rw

is ***

• Perl6 では引数は読み取り専用

•引数の値を変更したい場合は is rw

•引数のコピーが欲しい場合は is copy

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

is rw を使うと

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

is copy を使うと

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

何も指定しなかった場合

gather ... take

gather ... take

• gather は遅延評価リストを返す

•評価時に gather ブロック内を走査

• take された要素を見つけて返す

my @list = gather { for 0 .. Inf { take $_ ** $_; }}

say @list[0..3]; # 1 1 4 27

簡単な例

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 }}

merge関数での使い方

まとめ

• 文法にちょっとした変更がたくさん• 演算子を定義できる• is *** で引数へのアクセスレベルを指定• 遅延評価ができる

ところで

Perl5 と Perl6 の関係

• 異なる言語• Perl6 は Perl5 をベースに設計されている• Perl6 の特徴の一部は Perl5 に移植されている

Perl6::Gather

use strict;use warnings;

use Perl6::Gather;

my @list = gather { for (0..100) { take $_ ** $_; }};

for (0..3) { print $list[$_], ' ';}print "\n";

# 1 1 4 27

top related