quotemetaはメタキャラクタをクゥオートする

HOPの8章がなかなかすすまん。3歩進んで2.5歩下がるというようなことを繰り返しているような。

8.1.1に出てくるquotemetaはメタ文字をクゥオートする組み込み関数

pirl @> quotemeta($/)
"\\\n"

と展開される。

この節は、ダイヤモンド演算子をエミュレートしつつ、更に$/の部分に正規表現を使えるようにするといった内容

ProductName Higher-order Perl: A Guide To Program Transformation
Mark Jason Dominus
Morgan Kaufmann Pub / ¥ 7,634 (2005-05-30)
通常24時間以内に発送

HOP 7章終了

今週は仕事がやたらと忙しかったり、送別だ歓迎だと飲みが重なったので思うように読みすすめられなかったが、7章はページ数が少ないのでなんとか読み終えた。

perlで高階関数をどうやるかって章。 

クロージャを使ってカリー化するんだがそれだと関数っぽく呼べないのでglobを使う。というようなテクニカルな部分に関して解説。プロトタイプ宣言の部分とか良くわからなかったが、中盤以降あまり興味が持てなかったのでちゃんと読んでないような。

ちなみに、perlでカリー化するモジュールはSub::Curryってのがあります。

http://www.kzfmix.com/blosxom_archive/Computer/Linux/fpython060914.html

HOP 6章終了

Higher-Order Perl 6章は無限ストリーム。SICPの3章あたりに対応してるので、SICPのcar,cdr,consで無限ストリームを扱うあたりを読んでいれば最初のほうはサクサク読めた。特にストリームの混ぜ合わせとかが面白い。

6.5がストリームを使ってREGEXから文字列を生成するという節。ここが結構わかりにくくて数ページずつくらいしか読み進められなかった。*(0回以上の繰り返し)の表現とか最初なかなか理解できなかったので、紙に書き下したりとかした。

6.6のNewton-Raphson MethodoもSICPで既に読んでたので、比較しながら読むと楽しい。ついでにループ判定の方法を使って数値の振動を発見する方法にふれてて面白かった。Gaucheクックブック循環リストを扱うのアルゴリズム。

エラトステネスの篩のストリーム

HOPの6章は無限ストリームを扱っているのだけれど、SICPの無限ストリームの章にあるエラトステネスの篩が出てこないので書いてみた。

HOPだとcar,cdr,consがそれぞれhead,tail,nodeとなってるのでそれにあわせてある。promiseは計算を遅延させるためのクロージャ。

use strict;
use warnings;
no warnings 'recursion';

sub promise (&) { $_[0] }

sub node{
  my ($h, $t) = @_;
  [$h, $t];
}

sub head {
  my ($ls) = @_;
  $ls->[0];
}

sub tail {
  my ($ls) = @_;
  if(is_promise($ls->[1])){
    $ls->[1] = $ls->[1]->();
  }
  $ls->[1];
}

sub is_promise {
  UNIVERSAL::isa($_[0],'CODE');
}

sub drop {
  my $h = head($_[0]);
  $_[0] = tail($_[0]);
  return $h;
}

sub filter (&$) {
  my $f = shift;
  my $s = shift;
  until(! $s || $f->(head($s))){
    drop($s);
  }
  return if ! $s;
  node(head($s),promise {filter($f, tail($s))});
}

sub sieve {
  my $s = shift;
  node(head($s),
       promise {sieve(filter {$_[0] % head($s)} tail($s))});
}

sub upfrom {
  my ($m) = @_;
  node($m, promise{ upfrom($m+1)});
}

sub show {
  my ($s,$n) = @_;
  while($s && (! defined $n || $n-- > 0)){
    print head($s), $";
    $s = tail($s);
  }
  print $/;
}

my $primes = sieve(upfrom(2));
show($primes,300);

これで、素数のストリームが生成される。

ProductName 計算機プログラムの構造と解釈
ジェラルド・ジェイ サスマン,ジュリー サスマン,ハロルド エイブルソン
ピアソンエデュケーション / ¥ 4,830 (2000-02)
通常24時間以内に発送

ProductName Higher-order Perl: A Guide To Program Transformation
Mark Jason Dominus
Morgan Kaufmann Pub / ¥ 7,608 (2005-05-30)
通常24時間以内に発送

無限ストリームは楽しい

perlの grep $_, @_;

HOP6.5でなんだコレは?と。($_,@_)なんてありなのかと思ったがどうも違った。

sub test {
  my ($h, @s) = grep $_, @_;
  print "h:\t$h\n";
  print "s:\t";
  print join ",",@s,"\n";
}

test(3,undef,1,4,5);

実行結果

h:      3
s:      1,4,5,

配列の中からundefを除く、($_,@_)っていう配列ではなくて grep {$_} @_みたいな感じのgrep tipsだった。

HOP 5章終了

三連休は読みまくった。あと、家族が留守のため集中できたので、再帰をイテレータに変えるという章を読み終えた。

ProductName Higher-order Perl: A Guide To Program Transformation
Mark Jason Dominus
Morgan Kaufmann Pub / ¥ 7,625 (2005-05-30)
通常24時間以内に発送

この章は後半が大変面白い。末尾再帰とかの話で末尾再帰にできればwhile,until,forみたいなループにすることができるって話題から、最後にフィボナッチ数みたいに再帰が複数ある場合に再帰を排除するっていうネタで10pageくらい割いてる。

特にフィボナッチから再帰を剥ぎ取る部分が非常に面白かった。再帰をperlの内部スタック表現を配列使って明示的に触れるようにすることで排除するヨっていう流れをステップバイステップで進んでいくんだけど、ついていくのに非常に苦労して、時には紙に書いたり、時には何度も読み返したり、そして時には犬の散歩をしたりと結局半日費やしたが、読み終えてそれだけの価値があったと思う。

次、無限ストリーム。楽しみな章。

HOP 4章終了

Higher-Order Perlの4章は100pageに及ぶイテレータの章。

ProductName Higher-order Perl: A Guide To Program Transformation
Mark Jason Dominus
Morgan Kaufmann Pub / ¥ 7,625 (2005-05-30)
通常24時間以内に発送

4.3.1のpermutationのところがかなり面白い。組み合わせをシーケンスにするとことか基底を列ごとに変える部分とか。4.3.2はゲノム配列の組み合わせ問題で懐かしさ満開、といっても僕はそのころはEMBOSSとかに頼っていたのであまりそういう問題に関して深く考えたことなかったな(既にツールとして色々あったし、、、)

4.4でイテレータ版のmapとgrep。これは色々と楽しそう。Iterator::Utilというモジュールがある。

後半は読み物色が強くなってて、イテレータの終わりとSQLでいうNULLにあたるものをどう区別していくかみたいな。一番最後にweb spideringの例が示してあってigrepとimapがかなりいい感じ。

HOP 4.5.7

Higher-Order Perl

hash,arrayのほかにクロージャもblessできる。

Perl におけるオブジェクト指向

Perl のオブジェクトを作るときは、まず組み込みのデータ型から適当なものを選びます。普通はハッシュを使うことが多いと思いますが、配列やクロージャ(無名サブルーチン)もオブジェクトに出来ます。

ProductName Higher-order Perl: A Guide To Program Transformation
Mark Jason Dominus
Morgan Kaufmann Pub / ¥ 7,625 (2005-05-30)
通常24時間以内に発送

いくつかのアクションを持つイテレータを用意したとき

$it->('next');

とか書かないといけないところを

sub Iter::next {$_[0]->('next')}

というような関数を用意する。更に、イテレータを受け取ってblessして返す関数を適用。

sub Iterator (&) { bless $_[0] => 'Iter'}

そうすると、

$it->next

というようなメソッド風呼び出しが行え、一種の構文糖衣的な使い方と考えておけばよいのだろう。

HOP 4.4.4

Higher Order Perlのappend()

  • listをイテレータにする関数を作る
  • イテレータをいくつかリストに突っ込む
  • さっきのlistをイテレータにする関数を使ってイテレータの詰まったリストをイテレータに

イテレータのappendの完成。素晴らしい。この流れでイテレータのzipとかもやれそう。

ProductName Higher-order Perl: A Guide To Program Transformation
Mark Jason Dominus
Morgan Kaufmann Pub / ¥ 7,625 (2005-05-30)
通常24時間以内に発送

perlでfunc {}

func {なんかコード} = func(sub {なんかコード})の略らしい

sub Testfunc (&){return $_[0]->();}
Testfunc {print "hello kzfm"};

これはうまく動くが(&)がないと

sub Testfunc {return $_[0]->();}
Testfunc {print "hello kzfm"};

下のようなエラーが出る。

Not a CODE reference at test.pl line 1.

デバッガ動かしてみると先にTestfunc {print "hello kzfm"}がブロックとして評価されて、その後Testfunc {return $_[0]->();}が評価されるので$_[0]がコードブロックじゃないといわれているようだ。

プロトタイプで(&)ってことはコードブロック受け取ってるってことだよな。無名関数ってコードブロックか、、、あーなんとなくわかってきた気が。やっと{}がlispの括弧に見えてきた。