SlideShare une entreprise Scribd logo
1  sur  92
Télécharger pour lire hors ligne
Perl 6 正規表現プログラミング
         楽土入門


   サ゗ボウズ・ラボ株式会社
          竹迫 良範
  <takesako@shibuya.pm.org>
自己紹介

2009/04/06    Cybozu University   2
Shibuya Perl Mongers 2代目リーダー




                          いまここ
My Parrot

2009/04/06      Cybozu University   4
My pretty Parrot (Cockatiel) 可愛的小奧姆




  Moshi-moshi ?




My Parrot can say “Hello” when the telephone rang.
另外的 Parrot 算術擅長

Parrot Assembler (PASM)
                      PASM
       set I1, 33
       set I2, 5
       mod I3, I1, I2
       if I3, REMA
       print "5 is an integer divisor of 33"
       branch DONE
 REMA: print "5 divides 33 with remainder "
       print I3
 DONE: print "¥n"
       end

           33÷5=6、余り2 を計算する
           (5 into 33 is 6, remainder 2)
Perl6 の実装方針(最初の戦略)

Parrot
  Perl6 を Parrot で書く
  Perl5 を Parrot で動くようにする (Ponie Project)
Perl 5 is alive.

             But …
2009/04/06    Cybozu University   8
Perl 5 “Hello, world!”
                     package Earth;sub Greet{
                   %_=('Y','~');$_='$;=!(Middle
                 Earth.age~~~<Eart~~~~~~~~~~~~~h
              .age)?!(defined$ti~~~~~~~~~~~mez~~~On
            e[2])?!(push@time~~~~~~~~~~~~~~~~Zone,loc
          ~altime())?rotation?~~~~~~~~~~~~~q~~?The Worl
         ~~d?:q:[¥w]::q=[¥~~~~~~~~~~~~~~~~~d~a-f]=:q?..~~
        ~~~?:q:.:;"42b3d3~~~~~~~~~~~~~~~~~~~~~728656c6c6f6
       ~~~~~0277f627c64672~~~~~~~~~~~~~~~~~~~~~b3072796e647
      ~~~~~~~42b3b3rg7d"=Ym~~~~~~~~~~~~~~~~~~~¥$;~~*¥;p~~~~u
     ~~~~~~~~~sh@_,$&;bless~~~~~~~~~~~~~~~~~~~~~~~~~$c~~~~~~~
     ~~~~~~~~~o~ntine~~~~~nt~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ~~~~~~~~~~~~~s=¥~~~~~~~$~~~~~~~~~~~~~~~~~~~~~~~pangaea~~~~
   ~~~~~~~~~~~~~~~;{l~~~~~~~~~~~~~~~~~~~~~~~~~~~~ocal@_;local$;
   ~~~~~~~~~~~~~~~~~="o~~~~~~~~~~~~~~~~~~~~~~~~~cean";$^A=(defi
   ~~~~~~~~~~~~~~~~~~~n~~~~~~~~~~~~~~~~~~~~~~~~~ed$continents)?
   ~~~~~~~~~~~~~~~~~~~(vec(~~~~~~~~~~~~~~~~~~~~~~$;, YYsplit(¥'
   ~~~~~~~~~~~~~~~~~¥',${¥$;}~~~~~~~~~~~~~~~~~~~~~~)%3,YYsplit(
   ~~~~~~~~~~~~~~~~q??,$;)**2-~~~~~~~~~~~~~~~~~~~~~~(($;=Ytr/oa
   ~~~~~~~~~~~~~~~~eiu//)**2))=~~~~~~~~~~~~~~~~~~~~~~=28160)?q:
   ~~~~~~~~~~~~~~~~~.::q?!?:¥'?~~~~~~~~~~~~~~~~~~~~~~¥';}$^A=Ys
    ~~~~~~~~~~~~~~~~:¥Q.¥E:pack(~~~~~~~~~~~~~~~~~~~~~~¥'h*¥',j
     ~~~~~~~~~~~~~~~~~oin(q(),~~~~~~~~~~~~~~~~~~~~~~~grep{$_=
     ~~~~~~~~~~~~~~~~~~Ym,$,,}~~~~~~~~~~~~~~~~~~~~~~~split("
       ~~~~~~~~~~~~~~~~~",@_~~~~~~~~~~~~~~~~~~~~~~~~~~[0]))
        ~~~~~~~~~~~~~~~~):e~~~~~~~~~~~~~~~~~~~~~~~~~~~gexe
         ~~~~~~~~~~~~~~~;$d~~~~~~~~~~~~~~~~~~~~~~~~~~~="s
          ~~~~~~~~~~~~~~ort~~~~~~~~~~~~~~~~~~~~~~~~~~<=
            ~~~~~~~~~~~~>,~~~~~~~~~~~~~~~~~~~~~~~~~~YY
              ~~~~~~~~~~~@_~~~~~~~~~~~~~~~~~~~~~~~~
                 ~~~~~~~~~"~~~~~~~~~~~~~~~~~~~';;
                   s,(~|¥r|¥n|¥s),,g;s.Y.¥x7e.g;
                     eval};Greet;'the world';

http://www.perlmonks.org/index.pl?node_id=329174    by jbware on Feb 15, 2004 at 21:08 UTC (#329174=obfuscated)
Unreadable

Perl5→
読みにくいプログラムを量産し続けるPerl5
Readable

   Perl6!
読みやすいプログラムを書けるPerl6になる!
Perl 6 では・・・

ね、簡単でしょ?




  say "Hello, world!";
Perl 6
              on
             Parrot
2009/04/06    Cybozu University   13
這個 Parrot 能說各種各樣的語言
O’REILLY
NOT’REALLY
2000
Perl6 言語仕様 (language specification)

1. Apocalypse(黙示録)
   Larry Wall が Perl6 のデザ゗ンについて語る
     Perl6 の歴史的な文書(33個のRFCがベース)
2. Exegesis(注釈)
   Perl6 を用いたサンプルコードや Perl5 との比較
     黙示録を Damian Conway が詳細に解説
3. Synopsis(概要)
   Perl6 の最新の言語仕様が書かれている
     黙示録のダ゗ジェスト版
Why Perl 6 ? (モチベーション)

Perl 5 は・・・
 場当たり的な拡張を繰り返し
 既に Perl5 のコードは理解不能な領域に
   C でゴリゴリ      職人技 (needs more C hacker)
Perl 6 の目指す方向
 せめて OO らしく
 他の言語で良いところは取り入れよう
 後方互換性は無視
 コンパ゗ラと実行環境の分離
   Parrot で VM 化
   No more C hacker
all your language are belong to us
        - Project Perl 6 -
Second System Syndrome   (The Mythical Man-Month)

 2度目にデザ゗ンするシステ
  ムは失敗作になりやすい説
   1度目のデザ゗ンは自分の能力
    を把握していないので慎重に
   3度目のデザ゗ンは何が普遍的
    で何が特殊なものか分かるので
    正確に作ることができる
   しかし2度目のデザ゗ンでは、
    最初のデザ゗ンで抑えたゕ゗デ
    ゕ・装飾を思い切り詰め込んで
    しまうので失敗作になりやすい
                            人月の神話―狼人間を撃つ銀の弾はない
 → Perl6 は構想10年!                ISBN: 4894716658
・・・
2005
救世主 Pugs の登場

Pugs = Perl6 User’s Golfing System
  Yet another Perl6 implementation




    → Perl6 が動いた!2005/02/06    (1|2)+(3|4)→(4|5|6)
Audrey Tang (唐鳳)

CPAN界隈で有名
 PARの作者
1981年生まれ
 国籍:台湾

 Perl6(Pugs)を Haskell で実装した天才プログラマー


   高橋メソッドを世界に輸出した人
   http://en.wikipedia.org/wiki/Audrey_Tang
Pugs の拡張性

            powered by
            Haskell
2010
待望の Perl6 – Rakudo Star リリース!
http://rakudo.org/
http://github.com/rakudo/star/downloads
Get your own Parrot!
34
5秒でわかる Perl 6

メソッドを -> ではなく . で書けるように
 なった
      Perl 5           Perl 6




$obj->method();   $obj.method();




 →   これで Perl も立派なOO言語の仲間入り!
終了
The End

          36
Perl 6 で失ったもの ~後方互換性~

文字列の連結 .(ドット)→ ~(チルダ)に
         Perl5                      Perl6
# メソッド呼び出し                 # メソッド呼び出し
$obj->method();            $obj.method();

sub func { return "x"; }   sub func { return "x"; }

# 文字列の連結                   # 文字列の連結
my $a = "str";             my $a = "str";
my $b = $a.func();         my $b = $a~func();


一時期 ” _ ” という案もあったが…スペース入れるのが面倒
subst 文字列の置換

Rakudo/bin/ufo より

sub path-to-module-name($path)   {
    $path.subst(/^'lib/'/, '')   ¥
         .subst(/¥.pm6?$/, '')   ¥
         .subst('/', '::', :g)   ;
}
OO
Perl 5
Sigils
$@%
配列とハッシュのゕクセス方法が変更

はじめての人にもわかりやすく
  変数のプレフゖクス $@% ルールが変更
         Perl5                    Perl6
my @array = (1, 2, 3);   my @array = (1, 2, 3);
my %hash = ('a'=> 1);    my %hash = ('a'=> 1);

# 配列のメンバにアクセス            # 配列のメンバにアクセス
my $x = $array[0];       my $x = @array[0];

# ハッシュのメンバにアクセス          # ハッシュのメンバにアクセス
my $y = $hash{'a'}       my $y = %hash{'a'}
Perl 5 の変数(sigils rules)


scalar         array hash
-------        ------ -------
$s             @a     %h
$$s            $a[0]       $h{'?'}
$s->foo        ☹           ☹
Perl 6 の変数(Sigils rule)


scalar         array      hash
-------        ------     -------
$s             @a         %h
$$s            @a[0]      %h<?>
$s.foo         @a.foo     %h.foo
☺
() 括弧省略

if, for, while, do ブロックでの(括弧省略)
 キータ゗プの量が少なくなった
         Perl5             Perl6

if ($a eq $b) {    if $a eq $b {
  print "a=b¥n";     say "a=b";
}                  }

while ($i > 0) {   while $i > 0 {
  $i--;              $i--;
}                  }
(例)

スペースのあり/なしで実行結果が違う
         Perl5                       Perl6
# スペースなし                    # スペースなし
print(1+2)*3;               print(1+2)*3;
                → 実行結果: 3                    → 実行結果: 3



# スペースあり                    # スペースあり
print (1+2)*3;              print (1+2)*3;
              → 実行結果: 3                      → 実行結果: 9
Neko operator(範囲演算子)

Damian Conway氏が OSCON2005 で発音
 http://www.rubyist.net/~matz/20050803.html
   末尾を含まない「..^」
   先頭を含まない「^..」
   先頭と末尾を含まない「^..^」

                Perl6
     my @a = (1..^5); # (1,2,3,4)
     my @b = (1^..5); # (2,3,4,5)
     my @c = (1^..^5); # (2,3,4)
ネコ演算子って・・・ちょwおまwww

neko operator
^..^


   ネコ耳モード♪


Damian Conway 日本の漫画好き?


                     http://www.amazon.co.jp/dp/4847034864/
zip でくれ
 Please give me!

                   49
使用例:zip でくれ
便利な zip

2つの配列を同時にループ
  順番を保存した重複する key と value の表現
             Perl5                            Perl6
my @key = ("x", "y", "x");         my @key = ("x", "y", "x");
my @value = (1, 2, 3);             my @value = (1, 2, 3);

for (my   $i=0; $i<@key; $i++) {   for zip(@key,@value) -> $a,$b {
  my $a   = $key[$i];                print "key:$a; value:$b¥n";
  my $b   = $value[$i];            }
  print   "key:$a; value:$b¥n";
}
実際には Z operator が使える

Rakudo では zip ではなく Z 演算子が実装
  (1,2) Z (3,4)  (1,3, 2,4)
         Rakudo                            Perl6
my @key = ("x", "y", "x");      my @key = ("x", "y", "x");
my @value = (1, 2, 3);          my @value = (1, 2, 3);

for @key Z @value -> $a,$b {    for zip(@key,@value) -> $a,$b {
  print "key:$a; value:$b¥n";     print "key:$a; value:$b¥n";
}                               }
Piping operators(<==, ==>)

                  Perl6
     @result = map { floor($^x / 2) }
               grep { /^ ¥d+ $/ }
               @data;


    @result <== map { floor($^x / 2) }
            <== grep { /^ ¥d+ $/ }
            <== @data;


    @data ==> grep { /^ ¥d+ $/ }
          ==> map { floor($^x / 2) }
          ==> @result;
// 演算子 (err 演算子)

左辺が undef のときのみ右辺を評価
 // defined or
 Perl5 でありがちなバグを回避
    0(ゼロ) や ”” (空文字列)の扱い
 それぞれ || → or, // → err に対応

         Perl5                      Perl6

$num = shift @ARGV || 1;   $num = shift @ARGS // 1;
$bar = func() or die;      $bar = func() err die;
// は C言語で単一行コメント(PL/I起源)


/*    C comment style    */
//    #include <stdio.h>

必ず Syntax Error になる記号
     # Shell - single line comment
     # Perl - single line comment
JavaScript // problem

var r = new RegExp(“pattern”);
var r = /pattern/;

これは何?
  //

 // start a single-line comment.
    To specify an empty regular expression,

 use    /(?:)/
正規表現
Perl 5  Perl 6
  別の言語
                  57
Perl5 正規表現  Perl6 Regex で変わるもの
 1. 基本パターン
    繰り返し *+? と選択 |
 2. マッチ演算子
    文字列のパターンマッチ m//
    スマートマッチ演算子 ~~
    文字列の置換 s///
 3. 修飾子
    複数行モード/m 修飾子の廃止
    文字列の先頭「¥A」末尾「¥z」の廃止
    スペースとコメントが自由に挿入できる
     モード/x がデフォルトに
    単一行モード/s の廃止
    /e 修飾子の廃止
    新しい修飾子の書き方
Perl5 正規表現  Perl6 Regex で変わるもの

4. キャプチャ
 キャプチャ括弧(…)と後方参照
 キャプチャを伴わない括弧 […]
5. メタキャラクタ
 文字クラスの定義 <[a-z]>
 定義済み文字クラスの参照 <class>
 変数展開 <$var>
 文字列 <'string'> のリテラル展開
 文字列配列 @strings のリテラル展開
Perl5 正規表現  Perl6 Regex の未来

6. クロージャ
 コードの実行 {code}
 マッチ失敗  {fail}
 繰り返し範囲 **{n..m}
7. ルール
 rule
 grammar
1. 基本パターン



            61
繰り返し *+? と選択 |

Perl 5                                Perl 6
/x*/     # xが0個以上繰り返し                 /x*/     # == Perl 5
/y+/     # yが1個以上繰り返し                 /y+/     # == Perl 5
/z?/     # zが0個以上1個以下                 /z?/     # == Perl 5
/foo|bar/ # fooまたはbar                 /foo|bar/ # == Perl 5


$_ = "aaa bbb ccc foo moo zoo";       $_ = "aaa bbb ccc foo moo zoo";
if (/aaax*/) { print "ok¥n" }         if /aaax*/ { say "ok" }
if (/b+/)   { print "ok¥n" }          if /b+/ { say "ok" }
if (/cccc?/) { print "ok¥n" }         if /cccc?/ { say "ok" }
if (/foo|bar|baz/) { print "ok¥n" }   if /foo|bar|baz/ { say "ok" }


                                                                        62
2. マッチ演算子



            63
文字列のパターンマッチ m//

Perl 5                                  Perl 6
 /pattern/                               /pattern/
m/pattern/                              m/pattern/
m{pattern}                              m{pattern}
qr/pattern/                             rx/pattern/ または regex{pattern}


$_ = "This is a pen.";                  $_ = "This is a pen.";
if (/This/) { print "ok¥n" }            if /This/ { say "ok" }
if (m/pen/) { print "ok¥n" }            if m/pen/ { say "ok" }
if (m{pen}) { print "ok¥n" }            if m{pen} { say "ok" }
unless (/not match/) { print "ok¥n" }   unless /not match/ { say "ok" }
if ($_ =~ qr/pen/) { print "ok¥n" }     if ($_ ~~ rx/pen/) { say "ok" }
スマートマッチ演算子 ~~

Perl 5                                          Perl 6
  $str =~ /pattern/                             $str ~~ /pattern/
  $str !~ /pattern/                             $str !~~ /pattern/
                                                /pattern/ ~~ $str
                                                /pattern/ !~~ $str



my $str = "This is a pen.";                     my $str = "This is a pen.";
if ($str =~ /This/) { print "ok¥n" }            if $str ~~ /This/ { say "ok" }
if ($str =~ m/pen/) { print "ok¥n" }            if $str ~~ m/pen/ { say "ok" }
## (m/pen/ =~ $str) とは書けない                      if m/pen/ ~~ $str { say "ok" }
if ($str !~ /not match/) { print "ok¥n" }       if $str !~~ /not match/ { say "ok" }
unless ($str ~~ /not match/) { print "ok¥n" }   unless $str ~~ /not match/ { say "ok" }
3. 修飾子



         66
複数行モード/m 修飾子の廃止

Perl 5                                   Perl 6

/^ pattern $/m                           /^^ pattern $$/


正規表現の修飾子/mで「^」と「$」のマッチ規則が変わる

my $lines = "aaa¥nbbb¥nccc¥n";           my $lines = "aaa¥nbbb¥nccc¥n";
if ($lines =~ /^b/m) { print "ok¥n" }    if $lines ~~ /^^b/ { say "ok" }
if ($lines =~ /bb$/m) { print "ok¥n" }   if $lines ~~ /bb$$/ { say "ok" }
if ($lines =~ /^bbb$/m) {                if $lines ~~ /^^bbb$$/ {
           print "ok¥n";                    say "ok" ;
}                                        }
文字列の先頭「¥A」末尾「¥z」の廃止

Perl 5                                   Perl 6

/¥A pattern ¥z/                          /^ pattern $/


複数行モード/m に影響しないゕンカー記号「¥A」「¥z」

my $str = "abracadabra";                 my $str = "abracadabra";
if ($str =~ /¥Aabra/) { print "ok¥n" }   if $str ~~ /^abra/ { say "ok" }
if ($str =~ /abra¥z/) { print "ok¥n" }   if $str ~~ /abra$/ { say "ok" }
if ($str =~ /¥Aabracadabra¥z/) {         if $str ~~ /^abracadabra$/ {
    print "ok¥n" ;                           say "ok" ;
}                                        }
スペースとコメントが自由に
 挿入できるモード/x がデフォルトに

Perl 5                            Perl 6
/ pattern1 # コメントをここに書く           / pattern1 # コメントをここに書く
 pattern2 pattern3                 pattern2 pattern3
 /x                                /



my $str = "abracadabra";          my $str = "abracadabra";

if ( $str =~ /  abra # ゕブラ        if ( $str ~~ /      abra # ゕブラ
                  ca # カ                                ca # カ
              d abra # ダブラ                          d abra # ダブラ
            /x       # 終了                         /        # 終了
  ) { print "ok¥n" }                   ) { say "ok" }

if ($str =~ / abra cad abra /x)   if $str ~~ / abra cad abra /
     { print "ok¥n" }                 { say "ok" }
スペースのマッチ

Perl 5                               Perl 6
/¥ /x                                /¥ /
/¥Q ¥E/x                             /<' '>/
/[ ¥t¥r¥n]/x                         /<space>/
/[ ¥t¥r¥n]+/x                        /<ws>/


my $str = "This is¥ta ¥n pen.";      my $str = "This is¥ta ¥n pen .";
if ($str =~ / This ¥ is     /x)      if $str ~~ / This ¥ is /
   { print "ok¥n" }                    { say "ok" }
if ($str =~ / This ¥Q ¥E is /x)      if $str ~~ / This <' '> is /
   { print "ok¥n" }                    { say "ok" }
if ($str =~ / is [ ¥t¥r¥n] a /x)     if $str ~~ / is <space> a /
   { print "ok¥n" }                    { say "ok" }
if ($str =~ / a [ ¥t¥r¥n]+ pen /x)   if $str ~~ / a <ws> pen /
   { print "ok¥n" }                    { say "ok" }
単一行モード/s の廃止

Perl 5                                        Perl 6
/./s # どんな文字(改行を含む)                           /./ # 改行を含むどんな文字
/./ # どんな文字も(改行は除く)                           /¥N/ # 改行以外のどんな文字も
/[¥x0D¥x0A]|¥x0D¥x0A/                         /¥n/ # どんな端末の改行にもマッチ

my $c = '/***********************             my $c = '/***********************
          * This is a C comment *                       * This is a C comment *
           ***********************/                      ***********************/
          #include <stdio.h>                            #include <stdio.h>
          /* first */                                   /* first */
          main() { printf("C"); }';                     main() { printf("C"); }';
if ($c =~ m/(¥/¥*.+?¥*¥/)/) {                 if $c ~~ m{( ¥/¥* ¥N+? ¥*¥/ )} {
  if ($1 eq "/* first */") { print "ok¥n" }     if $0 eq "/* first */" { say "ok" }
}                                             }
if ($c =~ m/(¥/¥*.+?¥*¥/)/s) {                if $c ~~ m{( ¥/¥* [.|¥n]+? ¥*¥/ )} {
  my $lines = $1;                               my $lines = $0;
  if ($lines =~ /comment/) { print "ok¥n" }     if $lines ~~ /comment/ { say "ok" }
}                                             }
/e 修飾子の廃止  どこでも {code}

Perl 5                                                    Perl 6

s/pattern/code/e                                          s/pattern/{code}/


sub cm2inch {                                             sub cm2inch($cm) {
  my ($cm) = @_;                                            sprintf('%.01f-inch', $cm / 6.5);
  sprintf('%.01f-inch', $cm / 6.5);                       }
}
my $floppy = "3.5-inch FDD";                              my $floppy = "3.5-inch FDD";
if ($floppy =~ s/(¥d+¥.¥d+)-inch/{ sprintf('%.02f-cm',    if $floppy ~~ s/(¥d+¥.¥d+)-inch/{ sprintf('%.02f-cm', $0 * 6.5) }/ {
      $1 * 6.5) }/ex) {                                     if $floppy eq "22.75-cm FDD" { say "ok" }
  if ($floppy eq "22.75-cm FDD") { print "ok¥n" }           if $floppy ~~ s/(¥d+¥.¥d+)-cm/{ &cm2inch($0) }/ {
  if ($floppy =~ s/(¥d+¥.¥d+)-cm/{ &cm2inch($1) }/ex) {       if $floppy eq "3.5-inch FDD" { say "ok" }
    if ($floppy eq "3.5-inch FDD") { print "ok¥n" }         }
  }                                                       }
}




                        cf. Acme::Hyde(単位変換) on CPAN
新しい修飾子の書き方

Perl 5                          Perl 6
m/pattern/i                     m/:i pattern/


s/pattern/replace/ig            s:g/pattern/replace/



my $imas = "とかしつくして";           my $imas = "とかしつくして";
if ($imas =~ s/し/ち/g) {         if $imas ~~ s:g/し/ち/ {
    if ($imas eq "とかちつくちて") {       if $imas eq "とかちつくちて" {
        print "ok¥n";                   say "ok";
    }                               }
}                               }
4. キャプチャ



           74
キャプチャ括弧(…)と後方参照

Perl 5                                          Perl 6

(…)〃¥1〃¥2〃¥3…                                   (…)〃$0〃$1〃$2…

                      括弧(…)でキャプチャして、同じ正規表現内で後方参照する

my $str = "abracadabra";                        my $str = "abracadabra";
if ($str =~ /(a)br¥1c/) { print "ok¥n" }        if $str ~~ /(a)br$0c/ { say "ok" }
if ($str =~ /(ab)racad$1ra/) { print "ok¥n" }   if $str ~~ /(ab)racad$0ra/ { say "ok" }
if ($str =~ /(a)(b)r$1c$2d$2$2ra/) {            if $str ~~ /(a)(b)r$0c$0d$0$1ra/ {
     print "ok¥n" ;                                 say "ok" ;
}                                               }
if ($1 eq "a") { print "ok¥n" }                 if ($0 eq "a") { say "ok" }
if ($2 eq "b") { print "ok¥n" }                 if ($1 eq "b") { say "ok" }


                 【覚え方】 日本円¥廃止
                                   ドル$決済でゼロスタート
キャプチャを伴わない括弧 […]

Perl 5                                          Perl 6

(?:pattern)                                     [pattern]


my @domain = ( "shibuya.pm.org",                my @domain = ( "shibuya.pm.org",
                "shibuya.pl"    ,                              "shibuya.pl"    ,
                "shibuyajs.org" ,                              "shibuyajs.org" ,
);                                              );
for (@domain) {                                 for @domain {
   if (/^(¥w+)(?:¥.|-)?(js|pm|pl)(?:.org)?$/)     if /^(¥w+) [¥.|¥-]? (js|pm|pl) [.org]? $/ {
{                                                    say "Hello, $0 $1 !";
      print "Hello, $1 $2 !¥n";                   }
   }                                            }
}


            ドメ゗ン名からコミュニテゖ名を判断し "Hello, shibuya pm !" と挨拶する
5. メタキャラクタ



             77
文字クラスの定義 <[a-z]>

Perl 5                                               Perl 6
[abc]                                                <[abc]>
[a-z]                                                <[a-z]>
[^xyz]                                               <-[xyz]>
[B-Y]                                                < <[A-Z]> - <[AZ]> >


my @files = ("Jcode.pm", "Encode.pm", "jcode.pl");   my @files = ("Jcode.pm", "Encode.pm", "jcode.pl");
foreach (@files) {                                   for @files {
    if (/ ( (?:J|En|j) code ¥. p[ml]) /x ) {             if / ( [J|En|j] code ¥. p<[ml]> ) / {
        if ($_ eq $1) { print "ok¥n" }                       if $_ eq $0 { say "ok" }
    }                                                    }
}                                                    }




                 "Jcode.pm", "Encode.pm", "jcode.pl" のどれにもマッチする正規表現
文字クラスの定義 <[a-z]>

Perl 5                                               Perl 6
¥x20        # 空白1文字                                  <space> # 空白1文字
¥s+         # 連続したスペース                               <ws> # 連続したスペース
¥.         # ドット                                     <dot> # ドット ※ <lt>, <gt>
[[:digit:]] # [0-9]                                  <digit> # 数字
[[:upper:]] # [A-Z]                                  <upper> # 英大文字
[[:lower:]] # [a-z]                                  <lower> # 英小文字
[[:alpha:]] # [A-Za-z]                               <alpha> # ゕルフゔベット
[[:alnum:]] # [A-Za-z0-9]                            <alnum> # ゕルフゔベットと数字


$_ = "123 abc ¥t 456 ijk ¥t 789 XYZ";                $_ = "123 abc ¥t 456 ijk ¥t 789 XYZ";
if (/ ([0-9]+) ¥ ([A-Za-z]+) /x) {                   if / (<digit>+) ¥ (<alpha>+) / {
  if ($1 eq "123" && $2 eq "abc") { print "ok¥n" }     if $0 eq "123" && $1 eq "abc" { say "ok" }
}                                                    }
if (/ ([A-Za-z]+) ¥s+ ([0-9]+) /x) {                 if / (<alpha>+) <ws> (<digit>+) / {
  if ($1 eq "abc" && $2 eq "456") { print "ok¥n" }     if $0 eq "abc" && $1 eq "456" { say "ok" }
}                                                    }
変数展開 <$var>

Perl 5                                     Perl 6

/ $var /x                                  / <$var> /


my $var = "(This|That) is a (pen|book)";   my $var =
my $text1 = "This is a pen";               "(This|That)<space>is<space>a<space>(pen|book)";
my $text2 = "That is a book";              my $text1 = "This is a pen";
if ($text1 =~ /$var/) {                    my $text2 = "That is a book";
    print "ok¥n";                          if ($text1 ~~ m/<$var>/) {
}                                              say "ok";
if ($text2 =~ /$var/) {                    }
    print "ok¥n";                          if ($text2 ~~ m/<$var>/) {
}                                              say "ok";
                                           }
文字列 <'string'> のリテラル展開

Perl 5                                        Perl 6
¥Q$var¥E                                      $var
¥Qstring¥E                                    <'string'>
¥$¥Qstring¥E                                  <'$string'>


my $err = "Can't locate Boofy.pm in ¥@INC";   my $err = "Can't locate Boofy.pm in ¥@INC";
my $soozy = "Boofy.pm";                       my $soozy = "Boofy.pm";
if ($err =~ /¥Q$soozy¥E/x) {                  if $err ~~ /$soozy/ {
   print "ok¥n";                                 say "ok";
}                                             }
if ($err =~ /¥@INC/x) {                       if $err ~~ /<'@INC'>/ {
   print "ok¥n";                                 say "ok";
}                                             }
文字列配列 @str のリテラル展開

Perl 5                                  Perl 6
$target ~~ / (?: ¥Q$str[0]¥E |
                                        $target ~~ / @str /
                 ¥Q$str[1]¥E | … ) /x


my @str = ("orz", "OTL", "_|~|-O");     my @str = ("orz", "OTL", "_|~|-O");
my $food = "pasta mista, peperini,      my $food = "pasta mista, peperini,
          capellini tagliati,                  capellini tagliati,
          orzi piccoli, stelline.";            orzi piccoli, stelline.";
if ($food =~ /(?: ¥Q$str[0]¥E
             | ¥Q$str[1]¥E              # Rakudo では未実装っぽい
             | ¥Q$str[2]¥E )/x)         if $food ~~ / @str / {
{                                          say "ok";
   print "ok¥n";                        }
}
6. クロージャ



           83
どこでもコード実行 {code}

 Perl 5                                   Perl 6
/pat(?{code})tern/ # 埋め込みコード              /pat{code}tern/
/pat(??{retcode})tern/ # 動的正規表現           /pat<{retcode}>tern/

                                              どこでもクロージャ{...}


 my $text = "pattern";                    my $text = "pattern";

 $text =~ m/pat(?{print "ok¥n"})tern/;
                                          $text ~~ m/pat{say "ok"}tern/;
 if ($text =~ m/pat(??{lc("TER")})n/) {
     print "ok¥n";
                                          if $text ~~ m/pat<{lc("TER")}>n/ {
 }                                            say "ok";
                                          }
マッチ失敗 {fail}                                   [これは便利]



Perl 5                                                 Perl 6

                                                       / (...) {fail} /

【例】 IPアドレスをチェックする正規表現
my $x = qr/(25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])/;   my   $x = / (¥d+) {fail if $0 > 255} /;
for (0..255) {                                         my   $ipv4 = /^ $x ¥. $x ¥. $x ¥. $x $/;
  /^($x)$/;                                            my   $addr = "192.168.1.33";
}
                                                       if   $addr ~~ /$ipv4/ {
my $addr = "192.168.1.33";
if ($addr =~ /^($x¥.$x¥.$x¥.$x)$/) {
                                                            say "ok";
   print "ok¥n";                                       }
}




    正規表現のクロージャ内で fail を呼ぶと〃現在のキャプチャ内のマッチ
    に失敗させることができる。これを応用すると、正規表現中に複雑な計
    算式やプログラムを組み込んでパターンマッチさせられる。
7. ルール



         86
正規表現のラ゗ブラリ化

Perl 6 Rules & Grammars
grammar Inventory {
   regex product { ¥d+ }
   regex quantity { ¥d+ }
   regex color { ¥S+ }
   regex description { ¥N* }
   regex TOP { ^^ <product> ¥s+ <quantity> ¥s+
           [
           | <description> ¥s+ '(' ¥s* <color> ¥s* ')'
           | <color> ¥s+ <description>
           ]
           $$
   }


Inventory.parse($source_lines);
Example

Target strings                                                                             Perl 6 code
# lib/MyProject/Test.pm          http://search.cpan.org/~ingy/Test-Base/lib/Test/Base.pm   grammar Test::Base::Spec {
package MyProject::Test;                                                                       rule spec { <block>* }
use Test::Base -Base;
use MyProject;
…                                                                                              rule block {
package MyProject::Test::Filter;                                                                 <head>
use Test::Base::Filter -base;                                                                    <comment>
sub my_filter {                                                                                  <section>*
  return MyProject->do_something(shift);                                                       }
}
# t/sample.t                                                                                   rule head {
use MyProject::Test;                                                                             <block_delim> [ <sp>+ <name> ]? ¥n
                                                                                               }
plan tests => 1 * blocks;
                                                                                               rule comment {
run_is input => 'expected';                                                                      [ <!section_delim> <line> ]*
                                                                                               }
sub local_filter {
  s/my/your/;                                                                                  rule section {
}
                                                                                                 <section_delim>
__END__                                                                                          <sp>+ <name>
                                                                                                 <sp>+ [ <filter> <sp>+ ]*
=== Test one (the name of the test)                                                              [ ':' <data> ¥n | ¥n <chunk> ]
--- input my_filter local_filter                                                               }
my
input                                                                                          rule block_delim { ¥=¥=¥= }
lines                                                                                          rule section_delim { ¥-¥-¥- }
--- expected
expected
output                                                                                         rule   line { ¥N* ¥n }
=== Test two                                                                                   rule   name { ¥N* }
This is an optional description                                                                rule   data { ¥N* }
of this particular test.                                                                       rule   filter { ¥S+ }
--- input my_filter
other                                                                                          rule chunk {
input                                                                                            [ <!block_delim> <!section_delim> <line> ]*
lines
--- expected                                                                                   }
other expected
output                                                                                     }
Named capture など
まだまだ紹介しきれない
便利な機能がいっぱい!


                    89
さらに詳しく


         90
参考URL

 Perl 6 rules - Wikipedia
    http://en.wikipedia.org/wiki/Perl_6_rules
 perl6: Apocalypse 5: Pattern Matching          (Larry Wall)
    http://dev.perl.org/perl6/doc/design/apo/A05.html
 perl6: Synopsis 5: Regexes and Rules       (Damian Conway)
    http://dev.perl.org/perl6/doc/design/syn/S05.html
 Perl 6 FAQ - Regexes and Grammars
    http://www.programmersheaven.com/2/Perl6-FAQ-Regex
 Perl6::Rules - Implements (most of) the Perl 6 regex syntax
    http://search.cpan.org/~dconway/Perl6-Rules/Rules.pm
 日本語
    Perl6 Rules(新たな正規表現)
       http://www9.ocn.ne.jp/~ymt/perl6/rules.html
Enjoy Perl 6




    Have fun!
           Perl 6 正規表現プログラミング楽土入門

                                    92

Contenu connexe

Plus de takesako

SECCON CTF セキュリティ競技会コンテスト開催について
SECCON CTF セキュリティ競技会コンテスト開催についてSECCON CTF セキュリティ競技会コンテスト開催について
SECCON CTF セキュリティ競技会コンテスト開催について
takesako
 
Node.js - JavaScript Thread Programming
Node.js - JavaScript Thread ProgrammingNode.js - JavaScript Thread Programming
Node.js - JavaScript Thread Programming
takesako
 
Node.js - sleep sort algorithm
Node.js - sleep sort algorithmNode.js - sleep sort algorithm
Node.js - sleep sort algorithm
takesako
 
正規表現‐もう一つのバベルの塔‐木村浩一
正規表現‐もう一つのバベルの塔‐木村浩一正規表現‐もう一つのバベルの塔‐木村浩一
正規表現‐もう一つのバベルの塔‐木村浩一
takesako
 
Devsumi2010 Ecmascript5 (ISO/IEC JTC1/SC22)
Devsumi2010 Ecmascript5 (ISO/IEC JTC1/SC22)Devsumi2010 Ecmascript5 (ISO/IEC JTC1/SC22)
Devsumi2010 Ecmascript5 (ISO/IEC JTC1/SC22)
takesako
 
Shibuya.pm#8 - ImageFight - HTML 2.0 New Browser Detection
Shibuya.pm#8 - ImageFight - HTML 2.0 New Browser DetectionShibuya.pm#8 - ImageFight - HTML 2.0 New Browser Detection
Shibuya.pm#8 - ImageFight - HTML 2.0 New Browser Detection
takesako
 

Plus de takesako (18)

SECCON CTF セキュリティ競技会コンテスト開催について
SECCON CTF セキュリティ競技会コンテスト開催についてSECCON CTF セキュリティ競技会コンテスト開催について
SECCON CTF セキュリティ競技会コンテスト開催について
 
Acme minechan
Acme minechanAcme minechan
Acme minechan
 
Node.js - JavaScript Thread Programming
Node.js - JavaScript Thread ProgrammingNode.js - JavaScript Thread Programming
Node.js - JavaScript Thread Programming
 
Node.js - sleep sort algorithm
Node.js - sleep sort algorithmNode.js - sleep sort algorithm
Node.js - sleep sort algorithm
 
x86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTx86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNT
 
再帰的 正規表現JSON Validator
再帰的 正規表現JSON Validator再帰的 正規表現JSON Validator
再帰的 正規表現JSON Validator
 
正規表現‐もう一つのバベルの塔‐木村浩一
正規表現‐もう一つのバベルの塔‐木村浩一正規表現‐もう一つのバベルの塔‐木村浩一
正規表現‐もう一つのバベルの塔‐木村浩一
 
That Goes Without Alpha-Num (or Does It ?) all your base10 are belong to us
That Goes Without Alpha-Num (or Does It ?) all your base10 are belong to usThat Goes Without Alpha-Num (or Does It ?) all your base10 are belong to us
That Goes Without Alpha-Num (or Does It ?) all your base10 are belong to us
 
Devsumi2010 Ecmascript5 (ISO/IEC JTC1/SC22)
Devsumi2010 Ecmascript5 (ISO/IEC JTC1/SC22)Devsumi2010 Ecmascript5 (ISO/IEC JTC1/SC22)
Devsumi2010 Ecmascript5 (ISO/IEC JTC1/SC22)
 
Perl x86 JIT Programming
Perl x86 JIT ProgrammingPerl x86 JIT Programming
Perl x86 JIT Programming
 
YAPC::Asia 2008 Closing Ceremony
YAPC::Asia 2008 Closing CeremonyYAPC::Asia 2008 Closing Ceremony
YAPC::Asia 2008 Closing Ceremony
 
HTML Binary Hacks & GIF89a Ployglot
HTML Binary Hacks & GIF89a PloyglotHTML Binary Hacks & GIF89a Ployglot
HTML Binary Hacks & GIF89a Ployglot
 
Devsumi2008 - YAPC::Asia 2008 Tokyo
Devsumi2008 - YAPC::Asia 2008 TokyoDevsumi2008 - YAPC::Asia 2008 Tokyo
Devsumi2008 - YAPC::Asia 2008 Tokyo
 
GIF89a Oldtype
GIF89a OldtypeGIF89a Oldtype
GIF89a Oldtype
 
Shibuyajs Digest
Shibuyajs DigestShibuyajs Digest
Shibuyajs Digest
 
HTML2.0 - digg - OSC2007-fall
HTML2.0 - digg - OSC2007-fallHTML2.0 - digg - OSC2007-fall
HTML2.0 - digg - OSC2007-fall
 
Shibuya.pm#8 - ImageFight - HTML 2.0 New Browser Detection
Shibuya.pm#8 - ImageFight - HTML 2.0 New Browser DetectionShibuya.pm#8 - ImageFight - HTML 2.0 New Browser Detection
Shibuya.pm#8 - ImageFight - HTML 2.0 New Browser Detection
 
Shibuyajs24 JavaScript.GIF x LiveConnect
Shibuyajs24 JavaScript.GIF x LiveConnectShibuyajs24 JavaScript.GIF x LiveConnect
Shibuyajs24 JavaScript.GIF x LiveConnect
 

Perl6 Regex Programming with Rakudo

  • 1. Perl 6 正規表現プログラミング 楽土入門 サ゗ボウズ・ラボ株式会社 竹迫 良範 <takesako@shibuya.pm.org>
  • 2. 自己紹介 2009/04/06 Cybozu University 2
  • 3. Shibuya Perl Mongers 2代目リーダー いまここ
  • 4. My Parrot 2009/04/06 Cybozu University 4
  • 5. My pretty Parrot (Cockatiel) 可愛的小奧姆 Moshi-moshi ? My Parrot can say “Hello” when the telephone rang.
  • 6. 另外的 Parrot 算術擅長 Parrot Assembler (PASM) PASM set I1, 33 set I2, 5 mod I3, I1, I2 if I3, REMA print "5 is an integer divisor of 33" branch DONE REMA: print "5 divides 33 with remainder " print I3 DONE: print "¥n" end 33÷5=6、余り2 を計算する (5 into 33 is 6, remainder 2)
  • 7. Perl6 の実装方針(最初の戦略) Parrot Perl6 を Parrot で書く Perl5 を Parrot で動くようにする (Ponie Project)
  • 8. Perl 5 is alive. But … 2009/04/06 Cybozu University 8
  • 9. Perl 5 “Hello, world!” package Earth;sub Greet{ %_=('Y','~');$_='$;=!(Middle Earth.age~~~<Eart~~~~~~~~~~~~~h .age)?!(defined$ti~~~~~~~~~~~mez~~~On e[2])?!(push@time~~~~~~~~~~~~~~~~Zone,loc ~altime())?rotation?~~~~~~~~~~~~~q~~?The Worl ~~d?:q:[¥w]::q=[¥~~~~~~~~~~~~~~~~~d~a-f]=:q?..~~ ~~~?:q:.:;"42b3d3~~~~~~~~~~~~~~~~~~~~~728656c6c6f6 ~~~~~0277f627c64672~~~~~~~~~~~~~~~~~~~~~b3072796e647 ~~~~~~~42b3b3rg7d"=Ym~~~~~~~~~~~~~~~~~~~¥$;~~*¥;p~~~~u ~~~~~~~~~sh@_,$&;bless~~~~~~~~~~~~~~~~~~~~~~~~~$c~~~~~~~ ~~~~~~~~~o~ntine~~~~~nt~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~s=¥~~~~~~~$~~~~~~~~~~~~~~~~~~~~~~~pangaea~~~~ ~~~~~~~~~~~~~~~;{l~~~~~~~~~~~~~~~~~~~~~~~~~~~~ocal@_;local$; ~~~~~~~~~~~~~~~~~="o~~~~~~~~~~~~~~~~~~~~~~~~~cean";$^A=(defi ~~~~~~~~~~~~~~~~~~~n~~~~~~~~~~~~~~~~~~~~~~~~~ed$continents)? ~~~~~~~~~~~~~~~~~~~(vec(~~~~~~~~~~~~~~~~~~~~~~$;, YYsplit(¥' ~~~~~~~~~~~~~~~~~¥',${¥$;}~~~~~~~~~~~~~~~~~~~~~~)%3,YYsplit( ~~~~~~~~~~~~~~~~q??,$;)**2-~~~~~~~~~~~~~~~~~~~~~~(($;=Ytr/oa ~~~~~~~~~~~~~~~~eiu//)**2))=~~~~~~~~~~~~~~~~~~~~~~=28160)?q: ~~~~~~~~~~~~~~~~~.::q?!?:¥'?~~~~~~~~~~~~~~~~~~~~~~¥';}$^A=Ys ~~~~~~~~~~~~~~~~:¥Q.¥E:pack(~~~~~~~~~~~~~~~~~~~~~~¥'h*¥',j ~~~~~~~~~~~~~~~~~oin(q(),~~~~~~~~~~~~~~~~~~~~~~~grep{$_= ~~~~~~~~~~~~~~~~~~Ym,$,,}~~~~~~~~~~~~~~~~~~~~~~~split(" ~~~~~~~~~~~~~~~~~",@_~~~~~~~~~~~~~~~~~~~~~~~~~~[0])) ~~~~~~~~~~~~~~~~):e~~~~~~~~~~~~~~~~~~~~~~~~~~~gexe ~~~~~~~~~~~~~~~;$d~~~~~~~~~~~~~~~~~~~~~~~~~~~="s ~~~~~~~~~~~~~~ort~~~~~~~~~~~~~~~~~~~~~~~~~~<= ~~~~~~~~~~~~>,~~~~~~~~~~~~~~~~~~~~~~~~~~YY ~~~~~~~~~~~@_~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~"~~~~~~~~~~~~~~~~~~~';; s,(~|¥r|¥n|¥s),,g;s.Y.¥x7e.g; eval};Greet;'the world'; http://www.perlmonks.org/index.pl?node_id=329174 by jbware on Feb 15, 2004 at 21:08 UTC (#329174=obfuscated)
  • 11. Readable Perl6! 読みやすいプログラムを書けるPerl6になる!
  • 13. Perl 6 on Parrot 2009/04/06 Cybozu University 13
  • 15.
  • 18.
  • 19. 2000
  • 20. Perl6 言語仕様 (language specification) 1. Apocalypse(黙示録)  Larry Wall が Perl6 のデザ゗ンについて語る  Perl6 の歴史的な文書(33個のRFCがベース) 2. Exegesis(注釈)  Perl6 を用いたサンプルコードや Perl5 との比較  黙示録を Damian Conway が詳細に解説 3. Synopsis(概要)  Perl6 の最新の言語仕様が書かれている  黙示録のダ゗ジェスト版
  • 21. Why Perl 6 ? (モチベーション) Perl 5 は・・・ 場当たり的な拡張を繰り返し 既に Perl5 のコードは理解不能な領域に C でゴリゴリ 職人技 (needs more C hacker) Perl 6 の目指す方向 せめて OO らしく 他の言語で良いところは取り入れよう 後方互換性は無視 コンパ゗ラと実行環境の分離 Parrot で VM 化 No more C hacker
  • 22. all your language are belong to us - Project Perl 6 -
  • 23. Second System Syndrome (The Mythical Man-Month)  2度目にデザ゗ンするシステ ムは失敗作になりやすい説  1度目のデザ゗ンは自分の能力 を把握していないので慎重に  3度目のデザ゗ンは何が普遍的 で何が特殊なものか分かるので 正確に作ることができる  しかし2度目のデザ゗ンでは、 最初のデザ゗ンで抑えたゕ゗デ ゕ・装飾を思い切り詰め込んで しまうので失敗作になりやすい 人月の神話―狼人間を撃つ銀の弾はない → Perl6 は構想10年! ISBN: 4894716658
  • 25. 2005
  • 26. 救世主 Pugs の登場 Pugs = Perl6 User’s Golfing System Yet another Perl6 implementation → Perl6 が動いた!2005/02/06 (1|2)+(3|4)→(4|5|6)
  • 27. Audrey Tang (唐鳳) CPAN界隈で有名 PARの作者 1981年生まれ 国籍:台湾 Perl6(Pugs)を Haskell で実装した天才プログラマー 高橋メソッドを世界に輸出した人 http://en.wikipedia.org/wiki/Audrey_Tang
  • 28. Pugs の拡張性 powered by Haskell
  • 29. 2010
  • 30. 待望の Perl6 – Rakudo Star リリース!
  • 33. Get your own Parrot!
  • 34. 34
  • 35. 5秒でわかる Perl 6 メソッドを -> ではなく . で書けるように なった Perl 5 Perl 6 $obj->method(); $obj.method(); → これで Perl も立派なOO言語の仲間入り!
  • 37. Perl 6 で失ったもの ~後方互換性~ 文字列の連結 .(ドット)→ ~(チルダ)に Perl5 Perl6 # メソッド呼び出し # メソッド呼び出し $obj->method(); $obj.method(); sub func { return "x"; } sub func { return "x"; } # 文字列の連結 # 文字列の連結 my $a = "str"; my $a = "str"; my $b = $a.func(); my $b = $a~func(); 一時期 ” _ ” という案もあったが…スペース入れるのが面倒
  • 38. subst 文字列の置換 Rakudo/bin/ufo より sub path-to-module-name($path) { $path.subst(/^'lib/'/, '') ¥ .subst(/¥.pm6?$/, '') ¥ .subst('/', '::', :g) ; }
  • 39. OO
  • 41. $@%
  • 42. 配列とハッシュのゕクセス方法が変更 はじめての人にもわかりやすく 変数のプレフゖクス $@% ルールが変更 Perl5 Perl6 my @array = (1, 2, 3); my @array = (1, 2, 3); my %hash = ('a'=> 1); my %hash = ('a'=> 1); # 配列のメンバにアクセス # 配列のメンバにアクセス my $x = $array[0]; my $x = @array[0]; # ハッシュのメンバにアクセス # ハッシュのメンバにアクセス my $y = $hash{'a'} my $y = %hash{'a'}
  • 43. Perl 5 の変数(sigils rules) scalar array hash ------- ------ ------- $s @a %h $$s $a[0] $h{'?'} $s->foo ☹ ☹
  • 44. Perl 6 の変数(Sigils rule) scalar array hash ------- ------ ------- $s @a %h $$s @a[0] %h<?> $s.foo @a.foo %h.foo ☺
  • 45. () 括弧省略 if, for, while, do ブロックでの(括弧省略) キータ゗プの量が少なくなった Perl5 Perl6 if ($a eq $b) { if $a eq $b { print "a=b¥n"; say "a=b"; } } while ($i > 0) { while $i > 0 { $i--; $i--; } }
  • 46. (例) スペースのあり/なしで実行結果が違う Perl5 Perl6 # スペースなし # スペースなし print(1+2)*3; print(1+2)*3; → 実行結果: 3 → 実行結果: 3 # スペースあり # スペースあり print (1+2)*3; print (1+2)*3; → 実行結果: 3 → 実行結果: 9
  • 47. Neko operator(範囲演算子) Damian Conway氏が OSCON2005 で発音 http://www.rubyist.net/~matz/20050803.html 末尾を含まない「..^」 先頭を含まない「^..」 先頭と末尾を含まない「^..^」 Perl6 my @a = (1..^5); # (1,2,3,4) my @b = (1^..5); # (2,3,4,5) my @c = (1^..^5); # (2,3,4)
  • 48. ネコ演算子って・・・ちょwおまwww neko operator ^..^ ネコ耳モード♪ Damian Conway 日本の漫画好き? http://www.amazon.co.jp/dp/4847034864/
  • 49. zip でくれ Please give me! 49
  • 51. 便利な zip 2つの配列を同時にループ 順番を保存した重複する key と value の表現 Perl5 Perl6 my @key = ("x", "y", "x"); my @key = ("x", "y", "x"); my @value = (1, 2, 3); my @value = (1, 2, 3); for (my $i=0; $i<@key; $i++) { for zip(@key,@value) -> $a,$b { my $a = $key[$i]; print "key:$a; value:$b¥n"; my $b = $value[$i]; } print "key:$a; value:$b¥n"; }
  • 52. 実際には Z operator が使える Rakudo では zip ではなく Z 演算子が実装 (1,2) Z (3,4)  (1,3, 2,4) Rakudo Perl6 my @key = ("x", "y", "x"); my @key = ("x", "y", "x"); my @value = (1, 2, 3); my @value = (1, 2, 3); for @key Z @value -> $a,$b { for zip(@key,@value) -> $a,$b { print "key:$a; value:$b¥n"; print "key:$a; value:$b¥n"; } }
  • 53. Piping operators(<==, ==>) Perl6 @result = map { floor($^x / 2) } grep { /^ ¥d+ $/ } @data; @result <== map { floor($^x / 2) } <== grep { /^ ¥d+ $/ } <== @data; @data ==> grep { /^ ¥d+ $/ } ==> map { floor($^x / 2) } ==> @result;
  • 54. // 演算子 (err 演算子) 左辺が undef のときのみ右辺を評価 // defined or Perl5 でありがちなバグを回避 0(ゼロ) や ”” (空文字列)の扱い それぞれ || → or, // → err に対応 Perl5 Perl6 $num = shift @ARGV || 1; $num = shift @ARGS // 1; $bar = func() or die; $bar = func() err die;
  • 55. // は C言語で単一行コメント(PL/I起源) /* C comment style */ // #include <stdio.h> 必ず Syntax Error になる記号 # Shell - single line comment # Perl - single line comment
  • 56. JavaScript // problem var r = new RegExp(“pattern”); var r = /pattern/; これは何? // // start a single-line comment. To specify an empty regular expression, use /(?:)/
  • 57. 正規表現 Perl 5  Perl 6 別の言語 57
  • 58. Perl5 正規表現  Perl6 Regex で変わるもの  1. 基本パターン  繰り返し *+? と選択 |  2. マッチ演算子  文字列のパターンマッチ m//  スマートマッチ演算子 ~~  文字列の置換 s///  3. 修飾子  複数行モード/m 修飾子の廃止  文字列の先頭「¥A」末尾「¥z」の廃止  スペースとコメントが自由に挿入できる モード/x がデフォルトに  単一行モード/s の廃止  /e 修飾子の廃止  新しい修飾子の書き方
  • 59. Perl5 正規表現  Perl6 Regex で変わるもの 4. キャプチャ キャプチャ括弧(…)と後方参照 キャプチャを伴わない括弧 […] 5. メタキャラクタ 文字クラスの定義 <[a-z]> 定義済み文字クラスの参照 <class> 変数展開 <$var> 文字列 <'string'> のリテラル展開 文字列配列 @strings のリテラル展開
  • 60. Perl5 正規表現  Perl6 Regex の未来 6. クロージャ コードの実行 {code} マッチ失敗 {fail} 繰り返し範囲 **{n..m} 7. ルール rule grammar
  • 62. 繰り返し *+? と選択 | Perl 5 Perl 6 /x*/ # xが0個以上繰り返し /x*/ # == Perl 5 /y+/ # yが1個以上繰り返し /y+/ # == Perl 5 /z?/ # zが0個以上1個以下 /z?/ # == Perl 5 /foo|bar/ # fooまたはbar /foo|bar/ # == Perl 5 $_ = "aaa bbb ccc foo moo zoo"; $_ = "aaa bbb ccc foo moo zoo"; if (/aaax*/) { print "ok¥n" } if /aaax*/ { say "ok" } if (/b+/) { print "ok¥n" } if /b+/ { say "ok" } if (/cccc?/) { print "ok¥n" } if /cccc?/ { say "ok" } if (/foo|bar|baz/) { print "ok¥n" } if /foo|bar|baz/ { say "ok" } 62
  • 64. 文字列のパターンマッチ m// Perl 5 Perl 6 /pattern/ /pattern/ m/pattern/ m/pattern/ m{pattern} m{pattern} qr/pattern/ rx/pattern/ または regex{pattern} $_ = "This is a pen."; $_ = "This is a pen."; if (/This/) { print "ok¥n" } if /This/ { say "ok" } if (m/pen/) { print "ok¥n" } if m/pen/ { say "ok" } if (m{pen}) { print "ok¥n" } if m{pen} { say "ok" } unless (/not match/) { print "ok¥n" } unless /not match/ { say "ok" } if ($_ =~ qr/pen/) { print "ok¥n" } if ($_ ~~ rx/pen/) { say "ok" }
  • 65. スマートマッチ演算子 ~~ Perl 5 Perl 6 $str =~ /pattern/ $str ~~ /pattern/ $str !~ /pattern/ $str !~~ /pattern/ /pattern/ ~~ $str /pattern/ !~~ $str my $str = "This is a pen."; my $str = "This is a pen."; if ($str =~ /This/) { print "ok¥n" } if $str ~~ /This/ { say "ok" } if ($str =~ m/pen/) { print "ok¥n" } if $str ~~ m/pen/ { say "ok" } ## (m/pen/ =~ $str) とは書けない if m/pen/ ~~ $str { say "ok" } if ($str !~ /not match/) { print "ok¥n" } if $str !~~ /not match/ { say "ok" } unless ($str ~~ /not match/) { print "ok¥n" } unless $str ~~ /not match/ { say "ok" }
  • 67. 複数行モード/m 修飾子の廃止 Perl 5 Perl 6 /^ pattern $/m /^^ pattern $$/ 正規表現の修飾子/mで「^」と「$」のマッチ規則が変わる my $lines = "aaa¥nbbb¥nccc¥n"; my $lines = "aaa¥nbbb¥nccc¥n"; if ($lines =~ /^b/m) { print "ok¥n" } if $lines ~~ /^^b/ { say "ok" } if ($lines =~ /bb$/m) { print "ok¥n" } if $lines ~~ /bb$$/ { say "ok" } if ($lines =~ /^bbb$/m) { if $lines ~~ /^^bbb$$/ { print "ok¥n"; say "ok" ; } }
  • 68. 文字列の先頭「¥A」末尾「¥z」の廃止 Perl 5 Perl 6 /¥A pattern ¥z/ /^ pattern $/ 複数行モード/m に影響しないゕンカー記号「¥A」「¥z」 my $str = "abracadabra"; my $str = "abracadabra"; if ($str =~ /¥Aabra/) { print "ok¥n" } if $str ~~ /^abra/ { say "ok" } if ($str =~ /abra¥z/) { print "ok¥n" } if $str ~~ /abra$/ { say "ok" } if ($str =~ /¥Aabracadabra¥z/) { if $str ~~ /^abracadabra$/ { print "ok¥n" ; say "ok" ; } }
  • 69. スペースとコメントが自由に 挿入できるモード/x がデフォルトに Perl 5 Perl 6 / pattern1 # コメントをここに書く / pattern1 # コメントをここに書く pattern2 pattern3 pattern2 pattern3 /x / my $str = "abracadabra"; my $str = "abracadabra"; if ( $str =~ / abra # ゕブラ if ( $str ~~ / abra # ゕブラ ca # カ ca # カ d abra # ダブラ d abra # ダブラ /x # 終了 / # 終了 ) { print "ok¥n" } ) { say "ok" } if ($str =~ / abra cad abra /x) if $str ~~ / abra cad abra / { print "ok¥n" } { say "ok" }
  • 70. スペースのマッチ Perl 5 Perl 6 /¥ /x /¥ / /¥Q ¥E/x /<' '>/ /[ ¥t¥r¥n]/x /<space>/ /[ ¥t¥r¥n]+/x /<ws>/ my $str = "This is¥ta ¥n pen."; my $str = "This is¥ta ¥n pen ."; if ($str =~ / This ¥ is /x) if $str ~~ / This ¥ is / { print "ok¥n" } { say "ok" } if ($str =~ / This ¥Q ¥E is /x) if $str ~~ / This <' '> is / { print "ok¥n" } { say "ok" } if ($str =~ / is [ ¥t¥r¥n] a /x) if $str ~~ / is <space> a / { print "ok¥n" } { say "ok" } if ($str =~ / a [ ¥t¥r¥n]+ pen /x) if $str ~~ / a <ws> pen / { print "ok¥n" } { say "ok" }
  • 71. 単一行モード/s の廃止 Perl 5 Perl 6 /./s # どんな文字(改行を含む) /./ # 改行を含むどんな文字 /./ # どんな文字も(改行は除く) /¥N/ # 改行以外のどんな文字も /[¥x0D¥x0A]|¥x0D¥x0A/ /¥n/ # どんな端末の改行にもマッチ my $c = '/*********************** my $c = '/*********************** * This is a C comment * * This is a C comment * ***********************/ ***********************/ #include <stdio.h> #include <stdio.h> /* first */ /* first */ main() { printf("C"); }'; main() { printf("C"); }'; if ($c =~ m/(¥/¥*.+?¥*¥/)/) { if $c ~~ m{( ¥/¥* ¥N+? ¥*¥/ )} { if ($1 eq "/* first */") { print "ok¥n" } if $0 eq "/* first */" { say "ok" } } } if ($c =~ m/(¥/¥*.+?¥*¥/)/s) { if $c ~~ m{( ¥/¥* [.|¥n]+? ¥*¥/ )} { my $lines = $1; my $lines = $0; if ($lines =~ /comment/) { print "ok¥n" } if $lines ~~ /comment/ { say "ok" } } }
  • 72. /e 修飾子の廃止  どこでも {code} Perl 5 Perl 6 s/pattern/code/e s/pattern/{code}/ sub cm2inch { sub cm2inch($cm) { my ($cm) = @_; sprintf('%.01f-inch', $cm / 6.5); sprintf('%.01f-inch', $cm / 6.5); } } my $floppy = "3.5-inch FDD"; my $floppy = "3.5-inch FDD"; if ($floppy =~ s/(¥d+¥.¥d+)-inch/{ sprintf('%.02f-cm', if $floppy ~~ s/(¥d+¥.¥d+)-inch/{ sprintf('%.02f-cm', $0 * 6.5) }/ { $1 * 6.5) }/ex) { if $floppy eq "22.75-cm FDD" { say "ok" } if ($floppy eq "22.75-cm FDD") { print "ok¥n" } if $floppy ~~ s/(¥d+¥.¥d+)-cm/{ &cm2inch($0) }/ { if ($floppy =~ s/(¥d+¥.¥d+)-cm/{ &cm2inch($1) }/ex) { if $floppy eq "3.5-inch FDD" { say "ok" } if ($floppy eq "3.5-inch FDD") { print "ok¥n" } } } } } cf. Acme::Hyde(単位変換) on CPAN
  • 73. 新しい修飾子の書き方 Perl 5 Perl 6 m/pattern/i m/:i pattern/ s/pattern/replace/ig s:g/pattern/replace/ my $imas = "とかしつくして"; my $imas = "とかしつくして"; if ($imas =~ s/し/ち/g) { if $imas ~~ s:g/し/ち/ { if ($imas eq "とかちつくちて") { if $imas eq "とかちつくちて" { print "ok¥n"; say "ok"; } } } }
  • 75. キャプチャ括弧(…)と後方参照 Perl 5 Perl 6 (…)〃¥1〃¥2〃¥3… (…)〃$0〃$1〃$2… 括弧(…)でキャプチャして、同じ正規表現内で後方参照する my $str = "abracadabra"; my $str = "abracadabra"; if ($str =~ /(a)br¥1c/) { print "ok¥n" } if $str ~~ /(a)br$0c/ { say "ok" } if ($str =~ /(ab)racad$1ra/) { print "ok¥n" } if $str ~~ /(ab)racad$0ra/ { say "ok" } if ($str =~ /(a)(b)r$1c$2d$2$2ra/) { if $str ~~ /(a)(b)r$0c$0d$0$1ra/ { print "ok¥n" ; say "ok" ; } } if ($1 eq "a") { print "ok¥n" } if ($0 eq "a") { say "ok" } if ($2 eq "b") { print "ok¥n" } if ($1 eq "b") { say "ok" } 【覚え方】 日本円¥廃止  ドル$決済でゼロスタート
  • 76. キャプチャを伴わない括弧 […] Perl 5 Perl 6 (?:pattern) [pattern] my @domain = ( "shibuya.pm.org", my @domain = ( "shibuya.pm.org", "shibuya.pl" , "shibuya.pl" , "shibuyajs.org" , "shibuyajs.org" , ); ); for (@domain) { for @domain { if (/^(¥w+)(?:¥.|-)?(js|pm|pl)(?:.org)?$/) if /^(¥w+) [¥.|¥-]? (js|pm|pl) [.org]? $/ { { say "Hello, $0 $1 !"; print "Hello, $1 $2 !¥n"; } } } } ドメ゗ン名からコミュニテゖ名を判断し "Hello, shibuya pm !" と挨拶する
  • 78. 文字クラスの定義 <[a-z]> Perl 5 Perl 6 [abc] <[abc]> [a-z] <[a-z]> [^xyz] <-[xyz]> [B-Y] < <[A-Z]> - <[AZ]> > my @files = ("Jcode.pm", "Encode.pm", "jcode.pl"); my @files = ("Jcode.pm", "Encode.pm", "jcode.pl"); foreach (@files) { for @files { if (/ ( (?:J|En|j) code ¥. p[ml]) /x ) { if / ( [J|En|j] code ¥. p<[ml]> ) / { if ($_ eq $1) { print "ok¥n" } if $_ eq $0 { say "ok" } } } } } "Jcode.pm", "Encode.pm", "jcode.pl" のどれにもマッチする正規表現
  • 79. 文字クラスの定義 <[a-z]> Perl 5 Perl 6 ¥x20 # 空白1文字 <space> # 空白1文字 ¥s+ # 連続したスペース <ws> # 連続したスペース ¥. # ドット <dot> # ドット ※ <lt>, <gt> [[:digit:]] # [0-9] <digit> # 数字 [[:upper:]] # [A-Z] <upper> # 英大文字 [[:lower:]] # [a-z] <lower> # 英小文字 [[:alpha:]] # [A-Za-z] <alpha> # ゕルフゔベット [[:alnum:]] # [A-Za-z0-9] <alnum> # ゕルフゔベットと数字 $_ = "123 abc ¥t 456 ijk ¥t 789 XYZ"; $_ = "123 abc ¥t 456 ijk ¥t 789 XYZ"; if (/ ([0-9]+) ¥ ([A-Za-z]+) /x) { if / (<digit>+) ¥ (<alpha>+) / { if ($1 eq "123" && $2 eq "abc") { print "ok¥n" } if $0 eq "123" && $1 eq "abc" { say "ok" } } } if (/ ([A-Za-z]+) ¥s+ ([0-9]+) /x) { if / (<alpha>+) <ws> (<digit>+) / { if ($1 eq "abc" && $2 eq "456") { print "ok¥n" } if $0 eq "abc" && $1 eq "456" { say "ok" } } }
  • 80. 変数展開 <$var> Perl 5 Perl 6 / $var /x / <$var> / my $var = "(This|That) is a (pen|book)"; my $var = my $text1 = "This is a pen"; "(This|That)<space>is<space>a<space>(pen|book)"; my $text2 = "That is a book"; my $text1 = "This is a pen"; if ($text1 =~ /$var/) { my $text2 = "That is a book"; print "ok¥n"; if ($text1 ~~ m/<$var>/) { } say "ok"; if ($text2 =~ /$var/) { } print "ok¥n"; if ($text2 ~~ m/<$var>/) { } say "ok"; }
  • 81. 文字列 <'string'> のリテラル展開 Perl 5 Perl 6 ¥Q$var¥E $var ¥Qstring¥E <'string'> ¥$¥Qstring¥E <'$string'> my $err = "Can't locate Boofy.pm in ¥@INC"; my $err = "Can't locate Boofy.pm in ¥@INC"; my $soozy = "Boofy.pm"; my $soozy = "Boofy.pm"; if ($err =~ /¥Q$soozy¥E/x) { if $err ~~ /$soozy/ { print "ok¥n"; say "ok"; } } if ($err =~ /¥@INC/x) { if $err ~~ /<'@INC'>/ { print "ok¥n"; say "ok"; } }
  • 82. 文字列配列 @str のリテラル展開 Perl 5 Perl 6 $target ~~ / (?: ¥Q$str[0]¥E | $target ~~ / @str / ¥Q$str[1]¥E | … ) /x my @str = ("orz", "OTL", "_|~|-O"); my @str = ("orz", "OTL", "_|~|-O"); my $food = "pasta mista, peperini, my $food = "pasta mista, peperini, capellini tagliati, capellini tagliati, orzi piccoli, stelline."; orzi piccoli, stelline."; if ($food =~ /(?: ¥Q$str[0]¥E | ¥Q$str[1]¥E # Rakudo では未実装っぽい | ¥Q$str[2]¥E )/x) if $food ~~ / @str / { { say "ok"; print "ok¥n"; } }
  • 84. どこでもコード実行 {code} Perl 5 Perl 6 /pat(?{code})tern/ # 埋め込みコード /pat{code}tern/ /pat(??{retcode})tern/ # 動的正規表現 /pat<{retcode}>tern/ どこでもクロージャ{...} my $text = "pattern"; my $text = "pattern"; $text =~ m/pat(?{print "ok¥n"})tern/; $text ~~ m/pat{say "ok"}tern/; if ($text =~ m/pat(??{lc("TER")})n/) { print "ok¥n"; if $text ~~ m/pat<{lc("TER")}>n/ { } say "ok"; }
  • 85. マッチ失敗 {fail} [これは便利] Perl 5 Perl 6 / (...) {fail} / 【例】 IPアドレスをチェックする正規表現 my $x = qr/(25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])/; my $x = / (¥d+) {fail if $0 > 255} /; for (0..255) { my $ipv4 = /^ $x ¥. $x ¥. $x ¥. $x $/; /^($x)$/; my $addr = "192.168.1.33"; } if $addr ~~ /$ipv4/ { my $addr = "192.168.1.33"; if ($addr =~ /^($x¥.$x¥.$x¥.$x)$/) { say "ok"; print "ok¥n"; } } 正規表現のクロージャ内で fail を呼ぶと〃現在のキャプチャ内のマッチ に失敗させることができる。これを応用すると、正規表現中に複雑な計 算式やプログラムを組み込んでパターンマッチさせられる。
  • 87. 正規表現のラ゗ブラリ化 Perl 6 Rules & Grammars grammar Inventory { regex product { ¥d+ } regex quantity { ¥d+ } regex color { ¥S+ } regex description { ¥N* } regex TOP { ^^ <product> ¥s+ <quantity> ¥s+ [ | <description> ¥s+ '(' ¥s* <color> ¥s* ')' | <color> ¥s+ <description> ] $$ } Inventory.parse($source_lines);
  • 88. Example Target strings Perl 6 code # lib/MyProject/Test.pm http://search.cpan.org/~ingy/Test-Base/lib/Test/Base.pm grammar Test::Base::Spec { package MyProject::Test; rule spec { <block>* } use Test::Base -Base; use MyProject; … rule block { package MyProject::Test::Filter; <head> use Test::Base::Filter -base; <comment> sub my_filter { <section>* return MyProject->do_something(shift); } } # t/sample.t rule head { use MyProject::Test; <block_delim> [ <sp>+ <name> ]? ¥n } plan tests => 1 * blocks; rule comment { run_is input => 'expected'; [ <!section_delim> <line> ]* } sub local_filter { s/my/your/; rule section { } <section_delim> __END__ <sp>+ <name> <sp>+ [ <filter> <sp>+ ]* === Test one (the name of the test) [ ':' <data> ¥n | ¥n <chunk> ] --- input my_filter local_filter } my input rule block_delim { ¥=¥=¥= } lines rule section_delim { ¥-¥-¥- } --- expected expected output rule line { ¥N* ¥n } === Test two rule name { ¥N* } This is an optional description rule data { ¥N* } of this particular test. rule filter { ¥S+ } --- input my_filter other rule chunk { input [ <!block_delim> <!section_delim> <line> ]* lines --- expected } other expected output }
  • 91. 参考URL  Perl 6 rules - Wikipedia  http://en.wikipedia.org/wiki/Perl_6_rules  perl6: Apocalypse 5: Pattern Matching (Larry Wall)  http://dev.perl.org/perl6/doc/design/apo/A05.html  perl6: Synopsis 5: Regexes and Rules (Damian Conway)  http://dev.perl.org/perl6/doc/design/syn/S05.html  Perl 6 FAQ - Regexes and Grammars  http://www.programmersheaven.com/2/Perl6-FAQ-Regex  Perl6::Rules - Implements (most of) the Perl 6 regex syntax  http://search.cpan.org/~dconway/Perl6-Rules/Rules.pm  日本語  Perl6 Rules(新たな正規表現)  http://www9.ocn.ne.jp/~ymt/perl6/rules.html
  • 92. Enjoy Perl 6 Have fun! Perl 6 正規表現プログラミング楽土入門 92