<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1815593124211758484</id><updated>2012-01-02T04:33:17.879+09:00</updated><category term='perl5'/><category term='currying'/><category term='scheme'/><category term='lisp'/><category term='perl-5-to-6'/><category term='tips'/><category term='perl6'/><category term='continuation'/><category term='project euler'/><category term='perl'/><title type='text'>僕のIT革命</title><subtitle type='html'>Perl/PHP/Schemeあたりの学習帖。&lt;br&gt;
Twitter ID: &lt;a href="http://twitter.com/outerinside"&gt;outerinside&lt;/a&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>77</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-4056400559927467106</id><published>2011-03-14T18:51:00.004+09:00</published><updated>2011-03-19T02:55:09.472+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>「Perlにもしあったらいいなぁと思う機能」は大体Perl6にあると思う</title><content type='html'>&lt;p&gt;&lt;em&gt;2011-03-19: 複数行コメントについて加筆しました。&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;背景&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/perlcodesample/20101212/1298764341"&gt;Perlにもしあったらいいなぁと思う機能 - サンプルコードによるPerl入門&lt;/a&gt;を読んでて「それPerl6でできるよ」と思ったので。一応Perlです。一応。&lt;/p&gt;

&lt;h2&gt;1. ダブルクォーテーションの中で関数が展開できる機能&lt;/h2&gt;

&lt;p&gt;ダブルクォート(&lt;code&gt;qq&lt;/code&gt;演算子)はエスケープシーケンス、スカラ、配列、ハッシュ、関数、クロージャを展開します:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;"aaa { $book.title } bbb"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Q&lt;/code&gt;クォート演算子でオレオレ展開ルールも作れます(Rakudoだとまだ動きませんが):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Q:function/funcall: &amp;amp;func()/;
Q:closure/closure: { ucfirst('hello') ~ ', world' }/;

# qq//と同じ
Q:qq/$scalar, @array[], %hash{}, &amp;amp;subroutine(), { 'closure' }/;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;2. メソッドにおけるオブジェクトの名前&lt;/h2&gt;

&lt;p&gt;自身を&lt;code&gt;self&lt;/code&gt;で参照できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Foo {
  has Str $.objective = 'world';
  method greet {
    say "Hello, { self.objective }";
  }
}
Foo.new.greet; # Hello, world
Foo.new(:objective&amp;lt;Perl6&amp;gt;).greet; # Hello, Perl6
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;3. データを簡単にダンプする標準関数&lt;/h2&gt;

&lt;p&gt;オブジェクトをPerl6コードにダンプする&lt;code&gt;.perl&lt;/code&gt;メソッドがあります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say 42.perl; # 42
say { foo =&amp;gt; 'bar', hoge =&amp;gt; qw/fuga piyo/ }.perl; # {"foo" =&amp;gt; "bar", "hoge" =&amp;gt; ("fuga", "piyo")}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;デバッグ用には変数名が分かり易いようにペア記法を組み合わせて、&lt;code&gt;note&lt;/code&gt;で標準エラー出力に書き出します(&lt;code&gt;warn&lt;/code&gt;は例外を投げるので注意):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $obj = Foo.new(:objective&amp;lt;Perl6&amp;gt;);
note :$obj.perl; # "obj" =&amp;gt; Foo.new(objective =&amp;gt; "Perl6")
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;4. ファイルの内容を一度に読み込むモジュール&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;slurp&lt;/code&gt;が組み込み関数（と組み込みオブジェクトのメソッド）です。ファイルオープンに失敗すると例外を投げます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;open('filename').slurp;
slurp 'filename';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;でもこれってPerl5でも&lt;a href="http://search.cpan.org/search?query=slurp"&gt;&lt;code&gt;File::Slurp&lt;/code&gt;とか色々ある気がする&lt;/a&gt;。&lt;/p&gt;

&lt;h2&gt;5. Mojo::Base程度の小さなクラスビルダー&lt;/h2&gt;

&lt;p&gt;最初からまともなOO機能が付いてきます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Vector2D {
  has Num $.x = 0;
  has Num $.y = 0;
  method squared_norm() { [+] ($.x, $.y).map: (* ** 2) }
  method norm() { self.squared_norm.sqrt }
}

class Vector3D is Vector2D {
  has Num $.z = 0;
  method squared_norm() { [+] ($.x, $.y, $.z).map: (* ** 2) }
}

multi sub prefix:&amp;lt;~&amp;gt;(Vector3D $v --&amp;gt; Str) { "&amp;lt;{ $v.x }, { $v.y }, { $v.z }&amp;gt;" }
multi sub infix:&amp;lt;-&amp;gt;(Vector3D $v, Vector3D $u --&amp;gt; Vector3D) {
  my ($x, $y, $z) = ($v.x, $v.y, $v.z) Z- ($u.x, $u.y, $u.z);
  Vector3D.new(:$x, :$y, :$z);
}

my $v = Vector3D.new(:x(1), :y(3.sqrt));
my $u = Vector3D.new(:x(1), :z(1));
my $delta = $v - $u;
say "{ ~$v } norm: { $v.norm }"; # &amp;lt;1, 1.73205080756888, 0&amp;gt; norm: 2
say "{ ~$u } norm: { $u.norm }"; # &amp;lt;1, 0, 1&amp;gt; norm: 1.4142135623731
say "{ ~$delta } norm: { $delta.norm }"; # &amp;lt;0, 1.73205080756888, -1&amp;gt; norm: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;6. Net::FTPのコマンドが失敗したときは自動的に例外を投げてほしい&lt;/h2&gt;

&lt;p&gt;好みの問題なのでパス。サブクラス作ってオーバーライドするのがセオリーでしょうか。&lt;/p&gt;

&lt;h2&gt;7. ハッシュスライスと配列スライスのための関数&lt;/h2&gt;

&lt;p&gt;リファレンスはAutovivifyされるので必要ありません:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my %hash = foo =&amp;gt; 'hoge', bar =&amp;gt; qw/hoge fuga/, baz =&amp;gt; 'piyopiyo';
my $hash_ref = %hash;
my @slice = $hash_ref&amp;lt;foo bar&amp;gt;; # ('hoge', ('hoge', 'fuga'))
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;8. Perlの最新の機能とstrictとwarningsとutf8とautodieをレキシカルに有効にするプラグマ&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;strict&lt;/code&gt;/&lt;code&gt;warnings&lt;/code&gt;/&lt;code&gt;autodie&lt;/code&gt;相当はデフォルト。Unicode関連はまだ策定中のようですが、Rakudoだと文字列はUTF-8です。&lt;/p&gt;

&lt;h2&gt;9. 複数行コメント&lt;/h2&gt;

&lt;p&gt;これはPerl6でもPODで書くことになっています(&lt;a href="http://perlcabal.org/syn/S02.html#Whitespace_and_Comments"&gt;S02&lt;/a&gt;)。&lt;code&gt;=begin comment&lt;/code&gt;と&lt;code&gt;=end comment&lt;/code&gt;で囲むか、&lt;code&gt;=for comment&lt;/code&gt;で空行までをコメントにします。
POD処理系は知らない(あるいはコメントだと知っている)フォーマットの内容は出力しないので、ドキュメントと混ざるとかそういう心配はありません。&lt;/p&gt;

&lt;p&gt;ちなみに&lt;code&gt;=cut&lt;/code&gt;は必要なくなりました（というか、なくなりました）。&lt;/p&gt;

&lt;p&gt;もう1つ、埋め込みコメント(Embedded comment)という範囲を指定したコメントも利用できます。&lt;code&gt;#`&lt;/code&gt;に続けて好きな区切り子を使って囲みます(ただし&lt;code&gt;#&lt;/code&gt;は駄目):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say 'hello, ' ~ #`( コメントは空白扱いなので文中に出現しても構わない ) 'world';
$obj\ #`( 空白が許されない場所ではUnspaceで取り除く必要がある ).method;

#`{{
  複数行コメントの例。カッコは重ね打ちもできる。
  この場合数と種類が対応した閉じカッコが出現するまでがコメントとして扱われる。
  } まだ閉じない。
  } ここもまだコメントの中。
}} # ここで閉じられる

#`/* Cっぽくしたいならこう書ける(*は単なるコメントの一部) */
#`「Unicodeでカッコとして定義された文字なら何でも使える。誰得」
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;埋め込みコメントの区切り子の扱いは&lt;code&gt;Q&lt;/code&gt;クォート演算子と同じです。&lt;/p&gt;

&lt;p&gt;蛇足ですが2つめの例で&lt;code&gt;$obj\ #`( ... )`.say&lt;/code&gt;とあるのはPerl6がオペランドと後置演算子(ここではメソッド呼び出しの&lt;code&gt;.&lt;/code&gt;)の間に空白の出現を許していないためで、バックスラッシュは余分な空白を取り除くためのものです。
この機能はUnspaceと呼ばれています。Cプリプロセッサやシェルで行末に置くバックスラッシュを他の空白やコメントにも一般化したものと思えば大体合ってます。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://perlcabal.org/syn/S02.html"&gt;Synopsis 02&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6_12.html"&gt;Perl 5 to 6 - 文字列、配列、ハッシュ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://outer-inside.blogspot.com/2011/03/perl-5-to-6_4414.html"&gt;Perl 5 to 6 - クォートと構文解析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://outer-inside.blogspot.com/2011/02/perl-5-to-6_15.html"&gt;Perl 5 to 6 - オブジェクトとクラス&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://outer-inside.blogspot.com/2011/03/perl-5-to-6-perl6.html"&gt;Perl 5 to 6 - 一般的なPerl6データ処理イディオム&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-4056400559927467106?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/4056400559927467106/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perlperl6.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4056400559927467106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4056400559927467106'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perlperl6.html' title='「Perlにもしあったらいいなぁと思う機能」は大体Perl6にあると思う'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-377009038787651022</id><published>2011-03-10T01:52:00.004+09:00</published><updated>2011-03-15T00:51:30.532+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='continuation'/><title type='text'>部分継続チュートリアル</title><content type='html'>&lt;h2&gt;この文書について&lt;/h2&gt;

&lt;p&gt;これは&lt;a href="http://community.schemewiki.org/"&gt;Community Scheme Wiki&lt;/a&gt;で公開されている&lt;a href="http://community.schemewiki.org/?composable-continuations-tutorial"&gt;composable-continuations-tutorial&lt;/a&gt;（2010年09月30日版）の日本語訳です。&lt;/p&gt;

&lt;p&gt;誤字脱字・誤訳などがありましたらコメントあるいはメールで御指摘いただけると幸いです。&lt;/p&gt;

&lt;p&gt;本訳は原文のライセンスに基づき&lt;a href="http://creativecommons.org/licenses/by-sa/2.0/"&gt;Creative Commons Attribution-ShareAlike 2.0 Generic&lt;/a&gt;の下で公開されます。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2006-2010 Community Scheme Wiki&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;本文&lt;/h2&gt;

&lt;p&gt;部分継続(Composable continuation)は継続区間を具象化することで制御を逆転させるものです。
ウンザリするほど複雑な概念を表す長ったらしいジャーゴンのように聞こえますが、実際はそうではありません。今からそれを説明します。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reset&lt;/code&gt;と&lt;code&gt;shift&lt;/code&gt;という2つのスペシャルフォームを導入するところから始めましょう&lt;a href="#footnote-1"&gt;[1]&lt;/a&gt;。
&lt;code&gt;(reset expression)&lt;/code&gt;は特別な継続を作るなりスタックに目印を付けるなりしてから&lt;code&gt;expression&lt;/code&gt;を評価します。簡単に言えば、&lt;code&gt;expression&lt;/code&gt;が評価されるとき、あとから参照できる評価中の情報が存在するということです。
実際には&lt;code&gt;shift&lt;/code&gt;がこの情報を参照します。&lt;code&gt;(shift variable expression)&lt;/code&gt;は目印のついた場所、つまり&lt;code&gt;reset&lt;/code&gt;を使った場所にジャンプし、その場所から&lt;code&gt;shift&lt;/code&gt;を呼び出した場所までのプログラムの断片を保存します; これはプログラムの区間を「部分継続」として知られる組み合わせ可能な手続きに具象化し、この手続きに&lt;code&gt;variable&lt;/code&gt;を束縛してから&lt;code&gt;expression&lt;/code&gt;を評価します。&lt;/p&gt;

&lt;p&gt;組み合わせ可能(Composable)という語はその手続きが呼び出し元に戻ってくるため、他の手続きと組み合わせられることから来ています。
Composable continuationの別名として例えば限定継続(Delimited continuation)や部分継続(Partial continuation)もありますが、ここでは一貫して「組み合わせ可能」という用語を使います(訳注: 日本語では「部分継続」が訳語としてメジャーなので、この語を用いることにします)。
組み合わせ可能という特性は&lt;code&gt;call-with-current-continuaton&lt;/code&gt;が生成する「脱出継続」と違う部分です。
脱出継続は戻ってきません——というより、制御をプログラムの別の場所に戻す効果があります——が、部分継続は戻ってきます。&lt;/p&gt;

&lt;p&gt;部分継続を呼び出すと、制御を&lt;code&gt;shift&lt;/code&gt;が呼ばれた場所に戻します。
しかし&lt;code&gt;reset&lt;/code&gt;に渡された式が評価された位置に制御が続けて戻るときは、&lt;code&gt;reset&lt;/code&gt;が呼ばれた位置に戻るのではなく、部分継続手続きが呼び出された位置に戻るのです!&lt;/p&gt;

&lt;p&gt;別の説明としてコード変形を示してみます&lt;a href="#footnote-2"&gt;[2]&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(reset (...A... (shift V E) ...B...))
; --&amp;gt;
(let ((V (lambda (x) (...A... x ...B...))))
  E)

(reset E)
; --&amp;gt;
E
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;一連の例が意味を理解するのに役立つでしょう。
まず最初に、&lt;code&gt;shift&lt;/code&gt;がない&lt;code&gt;(reset expression)&lt;/code&gt;は末尾再帰を考えなければ&lt;code&gt;expression&lt;/code&gt;の評価と同じです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(+ 1 (reset (+ 2 3)))
;Value: 6

(cons 1 (reset (cons 2 '())))
;Value: (1 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;次に&lt;code&gt;shift&lt;/code&gt;を加えます。&lt;code&gt;shift&lt;/code&gt;で作られた部分継続を呼び出さなければ、&lt;code&gt;shift&lt;/code&gt;は自身とそれを動的スコープで内包している&lt;code&gt;reset&lt;/code&gt;の間の一切を捨てる効果があります。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(+ 1 (reset (+ 2 (shift k
                   ;; Kは無視
                   3))))
;Value: 4

(cons 1 (reset (cons 2 (shift k
                         ;; kは無視
                         (cons 3 '())))))
;Value: (1 3)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;問題: もし&lt;code&gt;(reset ... shift)&lt;/code&gt;内で&lt;code&gt;k&lt;/code&gt;を適用したらどうなるでしょう?&lt;/p&gt;

&lt;p&gt;次に部分継続を使ってみましょう。これは&lt;code&gt;(lambda (x) (+ 2 x))&lt;/code&gt;や&lt;code&gt;(lambda (x) (cons 2 x))&lt;/code&gt;と同じになります; これは&lt;code&gt;reset&lt;/code&gt;に渡した式の&lt;code&gt;shift&lt;/code&gt;呼び出しをすべて引数&lt;code&gt;x&lt;/code&gt;で置き換えた1引数関数を作ることで確認できます。これこそが「制御の逆転」の意味するところです: プログラムの評価の一部が関数として具象化されているのです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(+ 1 (reset (+ 2 (shift k
                   (+ 3 (k 4))))))
; --&amp;gt;
(+ 1 (let ((k (lambda (x) (+ 2 x))))
       (+ 3 (k 4))))
; --&amp;gt;
(+ 1 (+ 3 (+ 2 4)))
;Value: 10

(cons 1 (reset (cons 2 (shift k
                         (cons 3 (k (cons 4 '())))))))
; --&amp;gt;
(cons 1 (let ((k (lambda (x) (cons 2 x))))
          (cons 3 (k (cons 4 '())))))
; --&amp;gt;
(cons 1 (cons 3 (cons 2 (cons 4 '()))))
;Value: (1 3 2 4)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;さらに、部分継続は複数回呼び出すこともできます; プログラムの一部を実行する単なる関数であり、何度も同じ部分を実行することができます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(+ 1 (reset (+ 2 (shift k
                   (+ 3 (k 5) (k 1))))))
; --&amp;gt;
(+ 1 (let ((k (lambda (x) (+ 2 x))))
       (+ 3 (k 5) (k 1))))
; --&amp;gt;
(+ 1 (+ 3 (+ 2 5) (+ 2 1)))
;Value: 14

(cons 1 (reset (cons 2 (shift k
                         (cons 3 (k (k (cons 4 '()))))))))
; --&amp;gt;
(cons 1 (let ((k (lambda (x) (cons 2 x))))
       (cons 3 (k (k (cons 4 '()))))))
; --&amp;gt;
(cons 1 (cons 3 (cons 2 (cons 2 (cons 4 '())))))
;Value: (1 3 2 2 4)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これらの例は多分恣意的で、実用的ではないように見えるでしょう。実際これらの例は恣意的ですが、その目的は&lt;code&gt;shift&lt;/code&gt;と&lt;code&gt;reset&lt;/code&gt;を簡潔な方法で説明するところにありました。
式変形は手作業で行うこともできますが、&lt;code&gt;shift&lt;/code&gt;と&lt;code&gt;reset&lt;/code&gt;の威力は全体的なコード変形を必要としない点にあります。
&lt;code&gt;shift&lt;/code&gt;と&lt;code&gt;reset&lt;/code&gt;は抽象の境界を越えて、字句的に手が届かないスコープの動的な制御をも逆転させることができます; つまり、部分継続はプログラムの様々な点を把握せずとも、その一部を関数に詰め込むことができるということです 。&lt;/p&gt;

&lt;p&gt;もっと洗練された例を挙げましょう。&lt;code&gt;for-each&lt;/code&gt;のような手続があったとして、&lt;code&gt;for-each&lt;/code&gt;やその類の手続が受け付けるようなコレクションを受け取ってその要素の遅延ストリームを返す手続を作りたいとします。これは&lt;code&gt;call-with-current-continuation&lt;/code&gt;3つと&lt;code&gt;set!&lt;/code&gt;を使って作ることができます。胃腸や心臓が弱い方は見ないほうが良いでしょう。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(define (for-each-&amp;gt;stream-maker for-each)
  (stream-lambda (collection)
    (call-with-current-continuation
      (lambda (return-cdr)
        (for-each
          (lambda (element)
            (call-with-current-continuation
              (lambda (return-to-for-each)
                (return-cdr
                  (stream-cons element
                    (call-with-current-continuation
                      (lambda (return-next-cdr)
                        (set! return-cdr return-next-cdr)
                        (return-to-for-each))))))))
          collection)
        (return-cdr stream-null)))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;明らかにこれは不細工です。コードが入れ子の深みに降りていくのに合わせてインデントが素敵なスロープを描いていますが、このコードを考えているときに思い浮かぶことは優雅さという概念についての考えだけでしょう。
しかしながら、このパターンは&lt;code&gt;shift&lt;/code&gt;と&lt;code&gt;reset&lt;/code&gt;が抽象化しているものによく似ています。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;return-cdr&lt;/code&gt;は&lt;code&gt;reset&lt;/code&gt;で評価される式の継続を表しています; これにはコレクションを走査する間、連続した出力ストリームの&lt;code&gt;cdr&lt;/code&gt;を返すために&lt;code&gt;return-next-cdr&lt;/code&gt;が代入されます。&lt;code&gt;shift&lt;/code&gt;同様、保存しておきたいプログラムの一部に入った時点で継続を具象化―—&lt;code&gt;return-to-for-each&lt;/code&gt;——し、次の&lt;code&gt;reset&lt;/code&gt;する位置、つまり&lt;code&gt;return-cdr&lt;/code&gt;に脱出しています。
保存した一部を使いたくなったら、あたかも部分継続を呼び出すように継続——これはストリームが次に返す&lt;code&gt;cdr&lt;/code&gt;の継続——を&lt;code&gt;return-next-cdr&lt;/code&gt;として具象化し、それを&lt;code&gt;return-cdr&lt;/code&gt;に代入してプログラムの一部が次にどこに戻れば良いか分かるようにしてから、&lt;code&gt;return-to-for-each&lt;/code&gt;を呼び出してプログラムの一部をもう一度実行しています。&lt;/p&gt;

&lt;p&gt;これは&lt;code&gt;shift&lt;/code&gt;と&lt;code&gt;reset&lt;/code&gt;を使ってもっとずっと簡単に表現できます：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(define (for-each-&amp;gt;stream-maker for-each)
  (stream-lambda (collection)
    (reset (begin
             (for-each (lambda (element)
                         (shift k
                           (stream-cons element (k))))
                       collection)
             stream-null))))
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;脚注&lt;/h2&gt;

&lt;p&gt;&lt;a id="footnote-1"&gt;[1]&lt;/a&gt;
スペシャルフォームの代わりに&lt;code&gt;(reset thunk)&lt;/code&gt;と&lt;code&gt;(shift receiver)&lt;/code&gt;という手続きを使うこともできますが、簡潔さとカラム幅、それから一般的な使い方で一行に収まるようにそうしませんでした。
&lt;code&gt;control&lt;/code&gt;と&lt;code&gt;prompt&lt;/code&gt;——このページのほとんどの例で同じ結果になるもう一対のよく知られた制御演算子——もあることを覚えておいて下さい。&lt;/p&gt;

&lt;p&gt;&lt;a id="footnote-2"&gt;[2]&lt;/a&gt;
この変形は厳密には正しくありません、本当はもう少し&lt;code&gt;reset&lt;/code&gt;を置く必要があります。
詳細はこの文書の範囲から外れる上、入れ子になった&lt;code&gt;shift&lt;/code&gt;と&lt;code&gt;reset&lt;/code&gt;を使うときしか関係のないことです。
が、完備性のため、必要ならここに完全な変形を示しておきます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(reset (...A... (shift K E) ...B...))
; --&amp;gt;
(let ((K (lambda (x) (reset (...A... x ...B...)))))
  (reset E))

(reset E)
; --&amp;gt;
E
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(ラムダ式の内側の&lt;code&gt;reset&lt;/code&gt;だけが&lt;code&gt;shift&lt;/code&gt;/&lt;code&gt;reset&lt;/code&gt;演算子と&lt;code&gt;control&lt;/code&gt;/&lt;code&gt;prompt&lt;/code&gt;演算子の相違点です)&lt;/p&gt;

&lt;h2&gt;実装&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://mumble.net/~campbell/scheme/shift-reset.scm"&gt;Riastradh氏による&lt;code&gt;shift&lt;/code&gt;と&lt;code&gt;reset&lt;/code&gt;の実装&lt;/a&gt;は&lt;code&gt;call-with-current-continuation&lt;/code&gt;に基づいており、非常に重く実用には低速ですが、可搬性があります。 &lt;/p&gt;

&lt;p&gt;&lt;a href="http://okmij.org/ftp/Computation/Continuations.html#delimcc-scheme"&gt;Oleg氏によるバージョン&lt;/a&gt;は継続が必要とする部分だけをキャプチャするのにトランポリンを使っています。これはメモリリークがないという利点を持ちますが、このトランポリンは「空の」継続の中に置くべきで、また期待する動作のために&lt;code&gt;call/cc&lt;/code&gt;を変更する必要があります。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://docs.racket-lang.org/reference/cont.html"&gt;PLT Scheme(訳注: Racketに改名しています)の&lt;code&gt;scheme/control&lt;/code&gt;ライブラリ&lt;/a&gt;には&lt;code&gt;shift&lt;/code&gt;/&lt;code&gt;reset&lt;/code&gt;やその他多数の制御演算子が論文へのリンク付きで収録されています。&lt;/p&gt;

&lt;p&gt;GasbichlerとSperber両氏による論文「Final Shift for Call/cc: Direct Implementation of Shift and Reset」は様々な実装技術の詳細を掘り下げています(&lt;a href="http://www-pu.informatik.uni-tuebingen.de/users/sperber/papers/"&gt;Sperber氏のオンラインで公開されている論文&lt;/a&gt;)。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-377009038787651022?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/377009038787651022/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/377009038787651022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/377009038787651022'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/blog-post.html' title='部分継続チュートリアル'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5458135242266762095</id><published>2011-03-08T23:35:00.001+09:00</published><updated>2011-03-08T23:36:30.761+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>BrainMac</title><content type='html'>&lt;p&gt;Macユーザーに馴染み易いプログラミング言語はどんなものかと考えたとき、当然それはApple関連のキーワードだけでプログラムできる言語に違いありません。&lt;/p&gt;

&lt;p&gt;そういうわけで作りました。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package Language::BrainMac;

use 5.010;
use strict;
use warnings;
use parent qw/Language::BF/;

sub bm2bf(_) {
  my $token = shift;
  given ($token) {
    return '+' when /^OS[89X]$/i;
    return '-' when /^iOS$/i;
    return '&amp;gt;' when /^NeXT$/i;
    return '&amp;lt;' when /^Apple$/i;
    return ',' when /^Mac$/i;
    return '.' when /^i(?:Phone|Pad|Pod)$/i;
    return '[' when /^Steve$/i;
    return ']' when /^Jobs$|^Woz(?:niak)?$/i;
    return $_;
  }
}

sub code {
  my ($self, $code) = @_;
  $self-&amp;gt;SUPER::code(join ' ', grep $_, map bm2bf, split /\s+/, $code);
}

{
  no warnings qw/once/;
  *parse = \&amp;amp;code;
}

1;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://search.cpan.org/~dankogai/Language-BF-0.03/"&gt;Language::BF&lt;/a&gt;の&lt;code&gt;code&lt;/code&gt;メソッドをオーバーライドしてトークン置き換えているだけです。
やってることはOokと同じわけで、つまりMacユーザーはオランウータンと(ry&lt;/p&gt;

&lt;p&gt;Hello worldはこんな感じで書けます。&lt;del&gt;マカー脳の恐怖&lt;/del&gt;&lt;ins&gt;非常に分かり易い&lt;/ins&gt;ですね:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env perl

use 5.010;
use strict;
use warnings;
use Language::BrainMac;

my $bm = Language::BrainMac-&amp;gt;new(do { local $/; &amp;lt;DATA&amp;gt; });
$bm-&amp;gt;run;
say $bm-&amp;gt;output;

__DATA__
OSX OSX OSX OSX OSX OSX OSX OS9 OSX OSX Steve iOS NeXT OSX OSX OSX OSX OSX OSX OSX OSX OSX OSX Apple Jobs NeXT OSX OSX OSX OSX iPhone
iOS iOS iOS iPhone
OSX OSX OSX OSX OSX OSX OSX iPod iPad
OSX OSX OSX iPhone
NeXT OSX OSX OSX OSX OSX OSX OSX OSX OSX OSX iPhone
NeXT OSX OSX OSX OSX OS8 Steve iOS NeXT OSX OSX OSX OSX OSX OSX OSX OSX Apple Woz NeXT iPad
Apple Apple Apple OSX OSX OSX OSX OSX OSX OSX OSX OSX OSX iPad
Apple OSX OSX OSX OSX Steve iOS NeXT iOS iOS iOS iOS iOS Apple Jobs NeXT iPod
Apple OSX OSX OSX Steve iOS NeXT OSX OSX OSX OSX OSX Apple Jobs NeXT iPhone
NeXT NeXT NeXT iOS iOS iOS iOS iOS iOS iOS iOS iPod
Apple Apple Apple Apple OSX OSX OSX OSX Steve iOS NeXT iOS iOS iOS iOS iOS Apple Wozniak NeXT OSX iPhone
OSX OSX OSX OSX OSX OSX iPad
iOS iOS iOS iOS iOS iOS iPad
OSX OSX OSX OSX OSX OSX OSX OSX iPod
OSX OSX OSX OSX OSX iPhone
NeXT NeXT NeXT OSX OSX OSX OSX OSX OSX OSX OSX OSX iPhone
Apple Apple iPad
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;実行結果:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;hello
(yet again)
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5458135242266762095?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5458135242266762095/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/brainmac.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5458135242266762095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5458135242266762095'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/brainmac.html' title='BrainMac'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-2833252696780539530</id><published>2011-03-07T16:15:00.001+09:00</published><updated>2011-03-07T16:15:37.960+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - カリー化</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/28-currying.html"&gt;"Perl 5 to 6" Lesson 28 - Currying&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 28 - カリー化&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;use v6;

my &amp;amp;f := &amp;amp;substr.assuming('Hello, World');
say f(0, 2);                # He
say f(3, 2);                # lo
say f(7);                   # World

say &amp;lt;a b c&amp;gt;.map: * x 2;     # aabbcc
say &amp;lt;a b c&amp;gt;.map: *.uc;      # ABC
for ^10 {
    print &amp;lt;R G B&amp;gt;.[$_ % *]; # RGBRGBRGBR
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;カリー化、あるいは部分適用とは関数やメソッドにいくつかの引数を与えて関数を生成する処理のことです。
これは打鍵数を節約し、また他の関数にコールバック関数を渡したいときに便利です。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"Hello, World"&lt;/code&gt;から簡単に部分文字列を取り出せる関数が欲しいと仮定しましょう。古典的なやり方は専用の関数を書くことです:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub f(*@a) {
    substr('Hello, World', |@a)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;&lt;code&gt;assuming&lt;/code&gt;によるカリー化&lt;/h3&gt;

&lt;p&gt;Perl6のコードオブジェクトは&lt;code&gt;assuming&lt;/code&gt;メソッドを持ちます。これは呼び出し元のコードオブジェクトに引数を適用し、その部分適用された関数を返します。&lt;/p&gt;

&lt;p&gt;my &amp;amp;f := &amp;amp;substr.assuming('Hello, World');&lt;/p&gt;

&lt;p&gt;これで&lt;code&gt;f(1, 2)&lt;/code&gt;が&lt;code&gt;substr('Hello, World', 1, 2)&lt;/code&gt;と等価になります。&lt;/p&gt;

&lt;p&gt;演算子は単に変な名前のサブルーチンなので、&lt;code&gt;assuming&lt;/code&gt;は演算子に対しても使えます。
与えられた数に2を足すサブルーチンが欲しければ次のように書けます&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my &amp;amp;add_two := &amp;amp;infix:&amp;lt;+&amp;gt;.assuming(2);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;しかしこれは長ったらしすぎるので、別の方法があります。&lt;/p&gt;

&lt;h3&gt;Whatever-Starによるカリー化&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;my &amp;amp;add_two := * + 2;
say add_two(4);         # 6
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;このアスタリスクスは&lt;em&gt;Whatever&lt;/em&gt;と呼ばれ、引数のプレースホルダです。したがって式全体はクロージャを返します。
複数のWhateverを1つの式に含めることもでき、その場合&lt;code&gt;*&lt;/code&gt;の項を形式的パラメータで置き換え、複数の引数を取るクロージャが作られます。
つまり&lt;code&gt;* * 5 + *&lt;/code&gt;は&lt;code&gt;-&amp;gt; $a, $b { $a * 5 + $b }&lt;/code&gt;と等価です。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $c = * * 5 + *;
say $c(10, 2);                # 52
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;2番目の&lt;code&gt;*&lt;/code&gt;は項ではなく中置演算子なのでWhateverによるカリー化の対象ではないことに注意して下さい。&lt;/p&gt;

&lt;p&gt;Whateverを使った式のクロージャへの昇格は構文に基づいてコンパイル時に行われます。これはつまり&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $star = *;
my $code = $star + 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;はクロージャを生成せず、次のようなメッセージを出して&lt;code&gt;die&lt;/code&gt;するということです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Can't take numeric value for object of type Whatever
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Whateverによるカリー化には&lt;code&gt;assuming&lt;/code&gt;よりも多様な使い方があります。最初の引数以外も簡単にカリー化できるからです:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say  ~(1, 3).map: 'hi' x *    # hi hihihi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これは文字列繰り返し演算子である&lt;code&gt;infix:&amp;lt;x&amp;gt;&lt;/code&gt;の第2引数をカリー化しているので、数値引数で呼び出されるとその数だけ&lt;code&gt;hi&lt;/code&gt;を連結した文字列を生成するクロージャを返します。&lt;/p&gt;

&lt;p&gt;メソッドの呼び出し元オブジェクトをWhateverにすることもできます。よって&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say &amp;lt;a b c&amp;gt;.map: *.uc;      # ABC
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;は引数に対して&lt;code&gt;uc&lt;/code&gt;メソッドを呼び出すクロージャになります。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;Perl5で関数プログラミングができることはMark Jason Dominusが&lt;em&gt;Higher Order Perl&lt;/em&gt;で明らかにしています。&lt;/p&gt;

&lt;p&gt;Perl6はこれをもっと簡単にしようと試みており、関数プログラミングの典型的な構造を作るための使い易いツールを提供しています。
カリー化とクロージャの容易な生成は関数プログラミングの鍵となるもので、例えば&lt;code&gt;map&lt;/code&gt;や&lt;code&gt;grep&lt;/code&gt;と組み合わせて使うデータ変換を非常に簡単に書けるようにします。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S02.html#Built-In_Data_Types"&gt;http://perlcabal.org/syn/S02.html#Built-In_Data_Types&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://hop.perl.plover.com/"&gt;http://hop.perl.plover.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Currying"&gt;http://en.wikipedia.org/wiki/Currying&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-2833252696780539530?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/2833252696780539530/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_07.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2833252696780539530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2833252696780539530'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_07.html' title='Perl 5 to 6 - カリー化'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-1680473931840485209</id><published>2011-03-07T15:51:00.002+09:00</published><updated>2011-03-07T16:04:35.737+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 一般的なPerl6データ処理イディオム</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/27-common-idioms.html"&gt;"Perl 5 to 6" Lesson 27 - Common Perl 6 data processing idiom&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 27 - 一般的なPerl6データ処理イディオム&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;# キーと値のリストからハッシュを作る:
# 方法1: スライス
my %hash; %hash{@keys} = @values;
# 方法2: メタ演算子
my %hash = @keys Z=&amp;gt; @values;

# 配列の各要素に真を対応づけたハッシュを作る:
my %exists = @keys Z=&amp;gt; 1 xx *;

# 値を指定された範囲に制限する。ここでは範囲は 0..10
my $x = -2;
say 0 max $x min 10;

# デバッグ用: 変数の内容を変数名込みでSTDERRに書き出す
note :$x.perl;

# 大文字小文字を区別せずにソートする
say @list.sort: *.lc;

# 必須アトリビュート
class Something {
    has $.required = die "Attribute 'required' is mandatory";
}
Something.new(required =&amp;gt; 2); # エラーなし
Something.new()               # ブーン
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;ある言語で生産性を発揮するには言語仕様を学ぶだけでは不十分です。むしろ具体的な問題の解法を覚えておく必要があります。
イディオムと呼ばれる一般的な使用法のパターンは、あなたが問題に直面したときに毎回車輪の再発明をしなくとも良いように手助けしてくれます。&lt;/p&gt;

&lt;p&gt;そこでPerl6でデータを扱う一般的なイディオムをいくつか集めました。&lt;/p&gt;

&lt;h3&gt;ハッシュ&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# キーと値のリストからハッシュを作る:
# 方法1: スライス
my %hash; %hash{@keys} = @values;
# 方法2: メタ演算子
my %hash = @keys Z=&amp;gt; @values;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;最初の方法はPerl5で使われていたものと同じです: スライスへの代入です。
2番目の方法はZip演算子&lt;code&gt;Z&lt;/code&gt;を使っています。これはリストをジッパーのように連結します: &lt;code&gt;1, 2, 3 Z 10, 20, 30&lt;/code&gt;は&lt;code&gt;1, 10, 2, 20, 3, 30&lt;/code&gt;になります。
&lt;code&gt;Z=&amp;gt;&lt;/code&gt;はメタ演算子で、Zipを&lt;code&gt;=&amp;gt;&lt;/code&gt;(ペア生成演算子)と組み合わせています。つまり&lt;code&gt;1, 2, 3 Z=&amp;gt; 10, 20, 30&lt;/code&gt;は&lt;code&gt;1 =&amp;gt; 10, 2 =&amp;gt; 20, 3 =&amp;gt; 30&lt;/code&gt;と評価されます。これをハッシュ変数に代入するとハッシュに変換されます。&lt;/p&gt;

&lt;p&gt;存在チェックの場合、ハッシュの値はそれが真理値コンテキストでTrueと評価されさえすれば何でも良いことがしばしばあります。
このような場合に配列あるいはキーのリストからハッシュを初期化する良い方法は&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my %exists = @keys Z=&amp;gt; 1 xx *;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これは右辺に遅延評価される1の無限リストを使っており、&lt;code&gt;Z&lt;/code&gt;は短い方のリストが使い切られた時点で止まることを利用しています。&lt;/p&gt;

&lt;h3&gt;数値&lt;/h3&gt;

&lt;p&gt;どこからか数値を取得し、予め決めた範囲内に収まるよう切り詰めたいことが時々あります(例えば配列の添字として使えるように)。&lt;/p&gt;

&lt;p&gt;Perl5では結局&lt;code&gt;$a = $b &amp;gt; $upper ? $upper : $b&lt;/code&gt;ともう一つ下限の条件を付けることでしばしば対処してきました。
中値演算子&lt;code&gt;max&lt;/code&gt;と&lt;code&gt;min&lt;/code&gt;を使えば、これはかなり簡潔化できます&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $in-range = $lower max $x min $upper;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;$lower max $x&lt;/code&gt;はどちらか大きい方の数値を返すので、範囲の下限に切り詰めることになります。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;min&lt;/code&gt;と&lt;code&gt;max&lt;/code&gt;は中置演算子なので、演算子自体も切り詰められます:&lt;/p&gt;

&lt;p&gt;$x max= 0;
 $x min= 10;&lt;/p&gt;

&lt;h3&gt;デバッグ&lt;/h3&gt;

&lt;p&gt;Perl5には&lt;code&gt;Data::Dumper&lt;/code&gt;があり、Perl6には&lt;code&gt;.perl&lt;/code&gt;メソッドがあります。
これらは元のデータ構造を可能な限り忠実に再現するコードを生成します。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:$var&lt;/code&gt;はペア(「コロンペア」)を生成し、変数名をキーとして使います(ただしシジルは除きます)。つまりこれは&lt;code&gt;var =&amp;gt; $var&lt;/code&gt;と同じです。
&lt;code&gt;note()&lt;/code&gt;は標準エラーストリームにデータを改行付きで書き出します。したがって&lt;code&gt;note :$var.perl&lt;/code&gt;はデバッグ用に変数の値を名前と一緒に表示する手軽な手段になります。&lt;/p&gt;

&lt;h3&gt;ソート&lt;/h3&gt;

&lt;p&gt;Perl5と同様に、組み込みの&lt;code&gt;sort&lt;/code&gt;は2引数の比較関数を取ることができ、その比較にしたがってソートを行います。
Perl5と違ってこれはちょっと賢く、関数が引数を1個しか取らない場合は自動的に変換を行ってくれます。&lt;/p&gt;

&lt;p&gt;一般に、変換を通した値同士で比較を行いたければPerl5では次のようにできました:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# 注意: ここからPerl5コード
my @sorted = sort { transform($a) cmp transform($b) } @values;

# あるいは、いわゆるシュワルツ変換を使って:
my @sorted = map { $_-&amp;gt;[1] }
             sort { $a-&amp;gt;[0] cmp $b-&amp;gt;[0] }
             map { [transform($_), $_] }
             @values
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;最初の方法は変換を繰り返し書く必要がある上、比較毎に変換が実行されます。
2番目の方法は変換された値を元の値と一緒に保持することでその問題を回避していますが、コード量がかなり多くなります。&lt;/p&gt;

&lt;p&gt;Perl6は変換関数が1引数の場合、2番目の方法を自動化(し、値毎の配列生成を避けることで少しだけ効率化)します:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @sorted = sort &amp;amp;transform, @values;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;必須アトリビュート&lt;/h3&gt;

&lt;p&gt;アトリビュートの存在を強制する典型的な方法は、コンストラクタ内——複数存在する場合は全コンストラクタ内——で存在確認をすることです。&lt;/p&gt;

&lt;p&gt;Perl6でもこれは動きますが、各アトリビュートのレベルで必須にする方が簡単かつ安全です:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;has $.attr = die "'attr' is mandatory";
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これはデフォルト値の機構を利用しています。値が与えられた場合はデフォルト値生成コードは実行されないので&lt;code&gt;die&lt;/code&gt;も呼ばれません。
いずれかのコンストラクタが値をセットし損ねると例外が投げられます。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;N/A&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-1680473931840485209?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/1680473931840485209/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6-perl6.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1680473931840485209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1680473931840485209'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6-perl6.html' title='Perl 5 to 6 - 一般的なPerl6データ処理イディオム'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3742929588299927130</id><published>2011-03-06T22:57:00.001+09:00</published><updated>2011-03-06T23:07:06.442+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 例外と制御例外</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/26-exceptions.html"&gt;"Perl 5 to 6" Lesson 26 - Exceptions and control exceptions&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 26 - 例外と制御例外&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;try {
    die "OH NOEZ";

    CATCH { 
        say "there was an error: $!";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;例外はその名前に反してまったく例外的なものではありません。実際のところPerl6では通常の制御フローの一部です。&lt;/p&gt;

&lt;p&gt;例外は潜在的なエラー(例えば0除算、存在しないメソッドの呼び出し、型チェック失敗)または&lt;code&gt;die&lt;/code&gt;その他の関数の明示的な呼び出しによって生成されます。&lt;/p&gt;

&lt;p&gt;例外が投げられるとプログラムは呼び出しフレームから&lt;code&gt;CATCH&lt;/code&gt;ブロックか&lt;code&gt;try&lt;/code&gt;ブロックを探し、スタックを完全に巻き戻します(つまりそれまでに呼び出された全部のサブルーチンから無理矢理戻ってくるということです)。
もし&lt;code&gt;CATCH&lt;/code&gt;も&lt;code&gt;try&lt;/code&gt;も見つからなければプログラムは終了し、運が良ければ役に立つエラーメッセージが表示されます。
どちらか一方が見つかった場合はエラーメッセージは特殊変数&lt;code&gt;$!&lt;/code&gt;に格納され、&lt;code&gt;CATCH&lt;/code&gt;ブロックが実行されます(&lt;code&gt;try&lt;/code&gt;ブロックに&lt;code&gt;CATCH&lt;/code&gt;ブロックがない場合、ブロックは&lt;code&gt;undef&lt;/code&gt;を返します)。&lt;/p&gt;

&lt;p&gt;ここまでの説明ではまだ例外が例外的なものに思えるかも知れませんが、エラー処理は些末なアプリケーションでもなければ不可欠です。
ただそればかりでなく、通常の&lt;code&gt;return&lt;/code&gt;文も例外を投げているのです!&lt;/p&gt;

&lt;p&gt;これは制御例外と呼ばれ、&lt;code&gt;CONTROL&lt;/code&gt;ブロックで捕捉することができ、そうしない場合はサブルーチン宣言で暗黙的に捕捉されます。&lt;/p&gt;

&lt;p&gt;次の例を考えてみて下さい:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use v6;
my $block = -&amp;gt; { return "block"; say "still here" };

sub s {
    $block.();
    return "sub";
}

say s();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;return "block"&lt;/code&gt;が制御例外を投げ、現在のブロックから抜ける(したがって&lt;code&gt;still here&lt;/code&gt;は表示されない)のみならず、サブルーチンからも抜けます。これは&lt;code&gt;sub s...&lt;/code&gt;宣言で捕捉されます。
ペイロード——この例では文字列——は戻り値として渡され、最後の行の&lt;code&gt;say&lt;/code&gt;がこれを表示します。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$block.()&lt;/code&gt;を&lt;code&gt;try { ... }&lt;/code&gt;ブロックの中に入れたり&lt;code&gt;CONTROL { ... }&lt;/code&gt;ブロックをサブルーチンの本体に置いたりすることで例外を捕捉できます。&lt;/p&gt;

&lt;p&gt;他のプログラミング言語とは逆に&lt;code&gt;CATCH&lt;/code&gt;/&lt;code&gt;CONTROL&lt;/code&gt;ブロックはエラーが捕捉されるスコープの(外ではなく)中にあり、字句的変数への完全なアクセスが与えられています。このことは役に立つエラーメッセージを作るのを容易にし、またエラーが処理される前に&lt;code&gt;DESTROY&lt;/code&gt;ブロックが実行されることを防ぎます。&lt;/p&gt;

&lt;h3&gt;投げられない例外&lt;/h3&gt;

&lt;p&gt;Perl6はマルチスレッドの、特に自動並列化の考えを取り入れています。
1スレッドの終了が全スレッドに影響することがないように、「ソフトな」例外が考案されました。&lt;/p&gt;

&lt;p&gt;関数が&lt;code&gt;fail($obj)&lt;/code&gt;を呼ぶと特別な未定義値を返します。これはペイロードに&lt;code&gt;$obj&lt;/code&gt;(大抵の場合はエラーメッセージ)とバックトレース(ファイル名と行番号)を格納しています。
この特殊な未定義値を確認なしに処理しようとすると通常の例外が投げられます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @files = &amp;lt;/etc/passwd /etc/shadow nonexisting&amp;gt;;
my @handles = hyper map { open($_) }, @files;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;この例の&lt;code&gt;hyper&lt;/code&gt;演算子は&lt;code&gt;map&lt;/code&gt;に可能な限り動作を並列化するよう伝えます。
&lt;code&gt;nonexisting&lt;/code&gt;ファイルのオープンに失敗した場合、通常の&lt;code&gt;die "No such file or directory"&lt;/code&gt;では他のファイルオープン処理も中断してしまいます。
しかし失敗したオープン処理は代わりに&lt;code&gt;fail("No such file or directory")&lt;/code&gt;を呼ぶので、呼び出し元は&lt;code&gt;@handles&lt;/code&gt;の内容を確認することができ、完全なエラーメッセージにもアクセスできます。&lt;/p&gt;

&lt;p&gt;ソフトな例外が気に入らない場合、プログラムの最初に&lt;code&gt;use fatal;&lt;/code&gt;と書くと&lt;code&gt;fail()&lt;/code&gt;から生じる例外が即座に投げられるようになります。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;良いプログラミング言語にはエラー状態を扱うための例外が必要です。
成功したかどうか戻り値をいつも確認することは厄介だし忘れがちです。&lt;/p&gt;

&lt;p&gt;伝統的な例外は暗黙の並列化にとっては有害なことがあるので、両者の最上の部分を組み合わせる解法が必要でした: 一度にすべてを殺してしまわず、またどんな情報も取りこぼしてしまわない方法がです。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3742929588299927130?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3742929588299927130/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_06.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3742929588299927130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3742929588299927130'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_06.html' title='Perl 5 to 6 - 例外と制御例外'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5249804424658391853</id><published>2011-03-05T16:52:00.001+09:00</published><updated>2011-03-05T16:54:43.097+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 交差メタ演算子</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/25-cross-meta-operator.html"&gt;"Perl 5 to 6" Lesson 25 - The Cross Meta Operator&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 25 - 交差メタ演算子&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;for &amp;lt;a b&amp;gt; X 1..3 -&amp;gt; $a, $b {
    print "$a: $b   ";
}
# 出力: a: 1  a: 2  a: 3  b: 1  b: 2  b: 3

.say for &amp;lt;a b c&amp;gt; X 1, 2;
# 出力: a1\n a2\n b1\n b2\n c1\n c2\n
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;交差演算子&lt;code&gt;X&lt;/code&gt;は2つ以上のリストのデカルト積を返します。
つまりどういうことかというと、最初のリストから1つ取って最初の要素に、2番目のリストから1つ取って2番目の要素に、といった具合で作り得るすべての組を返します。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;X&lt;/code&gt;の後に演算子を付けるとそれが組のすべての要素に対して適用され、その結果が代わりに返されます。
よって&lt;code&gt;1, 2 X+ 3, 6&lt;/code&gt;は&lt;code&gt;1+3, 1+6, 2+3, 2+6&lt;/code&gt;(当然&lt;code&gt;4, 7, 5, 8&lt;/code&gt;と評価されます)を返します。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;2つ以上のリストの取り得る組み合わせをすべて走査しなければならないことはよくあります。交差演算子はそれを1つの走査に濃縮できるので、プログラムを簡潔にし、字下げのレベルを1つ減らせます。&lt;/p&gt;

&lt;p&gt;メタ演算子としての使用法は時としてループを完全になくすことができます。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S03.html#Cross_operators"&gt;http://perlcabal.org/syn/S03.html#Cross_operators&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5249804424658391853?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5249804424658391853/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_6474.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5249804424658391853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5249804424658391853'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_6474.html' title='Perl 5 to 6 - 交差メタ演算子'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-2451661884246797624</id><published>2011-03-05T01:26:00.000+09:00</published><updated>2011-03-05T01:29:02.473+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 縮約メタ演算子</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/24-reduce-meta-operator.html"&gt;"Perl 5 to 6" Lesson 24 - The Reduction Meta Operator&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 24 - 縮約メタ演算子&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;say [+] 1, 2, 3;    # 6
say [+] ();         # 0
say [~] &amp;lt;a b&amp;gt;;      # ab
say [**] 2, 3, 4;   # 2417851639229258349412352

[\+] 1, 2, 3, 4     # 1, 3, 6, 10
[\**] 2, 3, 4       # 4, 81, 2417851639229258349412352

if [&amp;lt;=] @list {
    say "ascending order";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;縮約メタ演算子&lt;code&gt;[...]&lt;/code&gt;は結合性のある中置演算子なら何でもリスト演算子に変換します。
これはあたかもリストの各要素間にその中置演算子が置かれたかのように働きます。つまり&lt;code&gt;[op] $i1, $i2, @rest&lt;/code&gt;は&lt;code&gt;$i1 op $i2 op @rest[0] op @rest[1] ...&lt;/code&gt;と書かれたのと同じ結果になります。&lt;/p&gt;

&lt;p&gt;これは&lt;code&gt;+&lt;/code&gt;演算子を総和関数に格上げし、&lt;code&gt;~&lt;/code&gt;演算子を(セパレータを空文字列にした)&lt;code&gt;join&lt;/code&gt;にするなど、非常に強力な構文です。
もし関数プログラミングに触れたことがあるなら、(LispやHaskellの)&lt;code&gt;foldl&lt;/code&gt;と&lt;code&gt;foldr&lt;/code&gt;を多分ご存知でしょう。
これらとは異なり&lt;code&gt;[...]&lt;/code&gt;は元の演算子の結合性に従うので、&lt;code&gt;[/] 1, 2, 3&lt;/code&gt;は&lt;code&gt;(1 / 2) / 3&lt;/code&gt;(左結合)として解釈され、&lt;code&gt;[**] 1, 2, 3&lt;/code&gt;は正しく&lt;code&gt;1 ** (2 ** 3)&lt;/code&gt;(右結合)として扱われます。&lt;/p&gt;

&lt;p&gt;他のすべての演算子と同様に空白は使うことができないので、&lt;code&gt;[+]&lt;/code&gt;とは書けますが&lt;code&gt;[ + ]&lt;/code&gt;は駄目です。&lt;/p&gt;

&lt;p&gt;比較演算子は連結することができるので、こんな風に書いたりもできます&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if    [==] @nums { say "all nums in @nums are the same" }
elsif [&amp;lt;]  @nums { say "@nums is in strict ascending order" }
elsif [&amp;lt;=] @nums { say "@nums is in ascending order"}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;代入演算子でさえ縮約することができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @a = 1..3;
[=] @a, 4;          # @a[0] = @a[1] = @a[2] = 4; と同じ
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;[...]&lt;/code&gt;がいつもスカラを返すことを覚えておいて下さい。なので&lt;code&gt;[,] @list&lt;/code&gt;は&lt;code&gt;[@list]&lt;/code&gt;と同じです。&lt;/p&gt;

&lt;h3&gt;部分結果の取得&lt;/h3&gt;

&lt;p&gt;バックスラッシュを使った特別な形式が在ります: &lt;code&gt;[\+]&lt;/code&gt;のような形式です。
これは部分評価結果のリストを返します。つまり&lt;code&gt;[\+] 1..3&lt;/code&gt;は&lt;code&gt;1, 1+2, 1+2+3&lt;/code&gt;というリストを返します。当然これは&lt;code&gt;1, 3, 6&lt;/code&gt;です。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[\~] 'a' .. 'd'     # &amp;lt;a ab abc abcd&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;右結合の演算子は右から左へ評価していくので、部分結果もその順になります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[\**] 1..3;         # 3, 2**3, 1**(2**3) これは 3, 8, 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;縮約演算子は複数組み合わせることができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[~] [\**] 1..3;     # "381"
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;プログラマは怠惰であり、2項演算子をリストの全要素に適用するためだけにループなど書きたくないものです。
&lt;code&gt;List.reduce&lt;/code&gt;が同様の機能を持ちますが、これはメタ演算子ほどには簡潔でありません(&lt;code&gt;[+] @list&lt;/code&gt;は&lt;code&gt;@list.reduce(&amp;amp;infix:&amp;lt;+&amp;gt;)&lt;/code&gt;になります)し、結合性の面倒を見てくれません。&lt;/p&gt;

&lt;p&gt;納得できないなら、この機能を使ってちょっと遊んでみて下さい(Pugsがほとんど実装しています)。本当に楽しいです。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S03.html#Reduction_operators"&gt;http://perlcabal.org/syn/S03.html#Reduction_operators&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.perlmonks.org/?node_id=716497"&gt;http://www.perlmonks.org/?node_id=716497&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-2451661884246797624?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/2451661884246797624/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_05.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2451661884246797624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2451661884246797624'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_05.html' title='Perl 5 to 6 - 縮約メタ演算子'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-1101991361111872897</id><published>2011-03-03T23:04:00.002+09:00</published><updated>2011-03-05T00:28:33.883+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - クォートと構文解析</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/23-quoting-and-parsing.html"&gt;"Perl 5 to 6" Lesson 23 - Quoting and Parsing&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 23 - クォートと構文解析&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;my @animals = &amp;lt;dog cat tiger&amp;gt;
# or
my @animals = qw/dog cat tiger/;
# or 

my $interface = q{eth0};
my $ips = q :s :x /ifconfig $interface/;

# -----------

sub if {
    warn "if() calls a sub\n";
}
if();
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;h3&gt;クォート&lt;/h3&gt;

&lt;p&gt;Perl6には強力な文字列クォート機構があり、文字列のあらゆる機能を完全に制御できます。&lt;/p&gt;

&lt;p&gt;Perl5にはシングルクォート、ダブルクォートそして&lt;code&gt;qw(...)&lt;/code&gt;(空白で分割するシングルクォート文字列リスト)があり、さらに&lt;code&gt;q(...)&lt;/code&gt;と&lt;code&gt;qq(...)&lt;/code&gt;がそれぞれシングルクォートとダブルクォートの同義語になっていました。&lt;/p&gt;

&lt;p&gt;一方のPerl6には&lt;code&gt;Q&lt;/code&gt;というクォート演算子が定義されていて、様々な修飾子を取ります。
&lt;code&gt;:b&lt;/code&gt;(バックスラッシュ)修飾子はバックスラッシュによる&lt;code&gt;\n&lt;/code&gt;のようなエスケープシーケンスの展開を許し、&lt;code&gt;:s&lt;/code&gt;修飾子はスカラ変数の展開を許し、&lt;code&gt;:c&lt;/code&gt;はクロージャ(&lt;code&gt;"1 + 2 = { 1 + 2 }"&lt;/code&gt;)の展開を許す、などなど。また&lt;code&gt;:w&lt;/code&gt;は&lt;code&gt;qw/.../&lt;/code&gt;が行うように単語を分割します。&lt;/p&gt;

&lt;p&gt;これらの修飾子は自由に組み合わせることができます。例えばスカラだけ展開し、他は展開しない&lt;code&gt;qw/.../&lt;/code&gt;を作りたくはないでしょうか。まったく問題在りません:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $stuff = "honey";
my @list = Q :w :s/milk toast $stuff with\tfunny\nescapes/;
say @list[*-1];                     # with\nfunny\nescapesと表示
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;利用できる修飾子のリストを示します。これは&lt;a href="http://perlcabal.org/syn/S02.html#Literals"&gt;S02&lt;/a&gt;からほとんどそのまま盗んできました。
これらはすべて長い名前も持ちますが、ここでは省略します。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;機能
    :q          \\と\q及び\'を展開する
    :b          その他の\nや\tのようなエスケープシーケンスも展開する
演算
    :x          シェルコマンドとして実行し、結果を返す
    :w          空白で分割する
    :ww         同上。クォートで囲まれた部分は分割しない
文字列展開
    :s          スカラを展開する     ($stuff)
    :a          配列を展開する       (@stuff[])
    :h          ハッシュを展開する   (%stuff{})
    :f          関数を展開する       (&amp;amp;stuff())
その他
    :c          クロージャを展開する ({code})
    :qq         :s、:a、:h、:f、:c、:bを展開する
    :regex      正規表現として解釈する
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;簡単のためにいくつか短い形式があります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;q       Q:q
qq      Q:qq
m       Q:regex
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;修飾子が短い形式の場合、&lt;code&gt;:&lt;/code&gt;も省略して1語として書くことができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;シンボル     元の形
qw          q:w
Qw          Q:w
qx          q:x
Qc          Q:c
# などなど
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ただし、Perl5プログラマが見落としそうな動作しない形式が1つあります: Perl6では小カッコを使って&lt;code&gt;qw(...)&lt;/code&gt;と書くことはできません。これはサブルーチン&lt;code&gt;qw&lt;/code&gt;の呼び出しとして解釈されます。&lt;/p&gt;

&lt;h3&gt;構文解析&lt;/h3&gt;

&lt;p&gt;これが構文解析の起点です: すべての&lt;code&gt;identifier(...)&lt;/code&gt;という形式はサブルーチン呼び出しとして解釈されます。そう、全部です。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if($x&amp;lt;3)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;はサブルーチン&lt;code&gt;if&lt;/code&gt;の呼び出しと解釈されます。空白を使って曖昧性を解消できます: &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if ($x &amp;lt; 3) { say '&amp;lt;3' }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;あるいは単にカッコを取り去って:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if $x &amp;lt; 3 { say '&amp;lt;3' }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これはつまりPerl6にはキーワードがないということです。正確に言えば&lt;code&gt;use&lt;/code&gt;とか&lt;code&gt;if&lt;/code&gt;のようなキーワードがありますが、これらは特別の構文の中で使われたときだけ特別扱いされます。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;クォート修飾子の様々な組み合わせは既に内部的に使われています。例えば&lt;code&gt;&amp;lt;...&amp;gt;&lt;/code&gt;を解析する&lt;code&gt;q:w&lt;/code&gt;や&lt;code&gt;m/.../&lt;/code&gt;を解析する&lt;code&gt;:regex&lt;/code&gt;です。
これらをユーザにも解放して柔軟性を向上させ、使いたいクォートの省略記法を提供するマクロを簡単に書けるようにすることは道理にかなっています。&lt;/p&gt;

&lt;p&gt;またキーワードの特別性を制限することで、「キーワード」の定義を書き換えたい時に後方互換性の問題を大幅に減らすことができます。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S02.html#Literals"&gt;http://perlcabal.org/syn/S02.html#Literals&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-1101991361111872897?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/1101991361111872897/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_4414.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1101991361111872897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1101991361111872897'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_4414.html' title='Perl 5 to 6 - クォートと構文解析'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-447372250649945378</id><published>2011-03-03T01:35:00.002+09:00</published><updated>2011-03-03T02:23:02.539+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 派生型</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/21-subset-types.html"&gt;"Perl 5 to 6" Lesson 21 - Subset Types&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 21 - 派生型&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;subset Squares of Int where { .sqrt.Int**2 == $_ };

multi sub square_root(Squares $x --&amp;gt; Int) {
    return $x.sqrt.Int;
}
multi sub square_root(Num $x --&amp;gt; Num) {
    return $x.sqrt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Javaプログラマは型のことをクラスかインタフェース(不具なクラスのようなもの)のように考えがちですが、その見方はPerl6においては狭すぎます。
型はもっと一般的に、コンテナが値に与えることができる制約です。「古典的な」制約はクラス&lt;code&gt;X&lt;/code&gt;あるいはそれを継承したクラスのインスタンスであることです。
Perl6にも&lt;code&gt;X&lt;/code&gt;クラスのインスタンスだとか&lt;code&gt;Y&lt;/code&gt;ロールを実装しているとか、あるいは&lt;em&gt;オブジェクトに対してこのコード片が真を返す&lt;/em&gt;といった制約があります。
最後に挙げたのが最も一般的なもので、これは派生型(Subset type)と呼ばれています:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;subset Even of Int where { $_ % 2 == 0 }
# これで他の型名と同様にEvenが使えるようになった

my Even $x = 2;
my Even $y = 3; # 型不一致エラー
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(試してみて下さい。Rakudoは派生型を既に実装していますが、派生型に基づいた多重ディスパッチはまだ実装されていません)(訳注: Rakudo* v2011.01で確認したところ、既に実装されているようです)&lt;/p&gt;

&lt;p&gt;シグネチャで無名派生型を使うこともできます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub foo (Int where { ... } $x) { ... }
# あるいは変数を前に出して
sub foo ($x of Int where { ... } ) { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;コードの形で任意の型制約を許すことは究極の拡張性を与えてくれます: 現状の型システムが気に喰わなくとも、派生型による自分の型システムで包むことができます。&lt;/p&gt;

&lt;p&gt;また、これはライブラリを容易に拡張可能にします: 扱えないデータに対して死ぬ代わりに、サブルーチンやメソッドは「悪い」データが単に多重ディスパッチャによって排除されると宣言できます。
もし排除されていたデータを誰かが扱いたくなったら、同名でそのデータを処理できる多重サブルーチンを簡単に追加できます。
この方法で例えば実数を扱う数学ライブラリを複素数を扱えるように拡張できます。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-447372250649945378?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/447372250649945378/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_03.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/447372250649945378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/447372250649945378'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6_03.html' title='Perl 5 to 6 - 派生型'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-7570399323663723359</id><published>2011-03-02T00:42:00.002+09:00</published><updated>2011-03-02T00:51:47.291+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - (似非)XMLのグラマー</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/20-a-grammar-for-xml.html"&gt;"Perl 5 to 6" Lesson 20 - A grammer for (pseudo) XML&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;p&gt;注記: XMLに関する用語の誤用(「整形式」と「妥当」を混同しているなど)がありますが、あくまで例なので原文通りに残しています。&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 20 - (似非)XMLのグラマー&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;grammar XML {
    token TOP   { ^ &amp;lt;xml&amp;gt; $ };
    token xml   { &amp;lt;text&amp;gt; [ &amp;lt;tag&amp;gt; &amp;lt;text&amp;gt; ]* };
    token text {  &amp;lt;-[&amp;lt;&amp;gt;&amp;amp;]&amp;gt;* };
    rule tag   {
        '&amp;lt;'(\w+) &amp;lt;attributes&amp;gt;*
        [
            | '/&amp;gt;'                 # 空タグ
            | '&amp;gt;'&amp;lt;xml&amp;gt;'&amp;lt;/' $0 '&amp;gt;'  # 開始タグと終了タグ
        ]
    };
    token attributes { \w+ '="' &amp;lt;-["&amp;lt;&amp;gt;]&amp;gt;* '"' };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;これまでの連載記事の焦点はPerl6言語であり、実装状況は気にしていませんでした。
これが空想上の言語でないことを示すため、またグラマーの能力を証明するために、このレッスンでは基本的なXMLを解析する、Rakudoで実行できるグラマーの開発をお見せします。&lt;/p&gt;

&lt;p&gt;Rakudoの入手とビルドは&lt;a href="http://rakudo.org/how-to-get-rakudo"&gt;http://rakudo.org/how-to-get-rakudo&lt;/a&gt;の指示にしたがって自分で行って下さい。&lt;/p&gt;

&lt;h3&gt;XMLの概念&lt;/h3&gt;

&lt;p&gt;私たちの用途の範囲ではXMLは非常に単純です: プレーンテキストと入れ子になったタグから成り、タグは属性を持つことがあります。
妥当なXMLであると(あるいはそうでないと)解析させたいテストケースをちょっとだけ用意しました:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @tests = (
    [1, 'abc'                       ],      # 1
    [1, '&amp;lt;a&amp;gt;&amp;lt;/a&amp;gt;'                   ],      # 2
    [1, '..&amp;lt;ab&amp;gt;foo&amp;lt;/ab&amp;gt;dd'          ],      # 3
    [1, '&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'           ],      # 4
    [1, '&amp;lt;a href="foo"&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'],      # 5
    [1, '&amp;lt;a empty="" &amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;' ],      # 6
    [1, '&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;c&amp;gt;&amp;lt;/c&amp;gt;&amp;lt;/a&amp;gt;'    ],      # 7
    [0, '&amp;lt;'                         ],      # 8
    [0, '&amp;lt;a&amp;gt;b&amp;lt;/b&amp;gt;'                  ],      # 9
    [0, '&amp;lt;a&amp;gt;b&amp;lt;/a'                   ],      # 10
    [0, '&amp;lt;a&amp;gt;b&amp;lt;/a href=""&amp;gt;'          ],      # 11
    [1, '&amp;lt;a/&amp;gt;'                      ],      # 12
    [1, '&amp;lt;a /&amp;gt;'                     ],      # 13
);

my $count = 1;
for @tests -&amp;gt; $t {
    my $s = $t[1];
    my $M = XML.parse($s);
    if !($M  xor $t[0]) {
        say "ok $count - '$s'";
    } else {
        say "not ok $count - '$s'";
    }
    $count++;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これは「良い」XMLと「悪い」XMLのリスト、そして&lt;code&gt;XML.parse($string)&lt;/code&gt;を呼び出してテストを走らせる小さなスクリプトです。
言語全体にマッチするルールは&lt;code&gt;TOP&lt;/code&gt;という名前にする約束になっています。&lt;/p&gt;

&lt;p&gt;(テスト1で分かるように単一のルートタグを必須にしていませんが、この制限を追加するのは些細なことです) &lt;/p&gt;

&lt;h3&gt;グラマーの開発&lt;/h3&gt;

&lt;p&gt;XMLのキモは当然タグの入れ子構造ですから、まず2番目のテストに着目することにしましょう。
テストスクリプトの先頭に以下のコードを置いて下さい:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grammar XML {
    token TOP   { ^ &amp;lt;tag&amp;gt; $ }
    token tag   {
        '&amp;lt;' (\w+) '&amp;gt;'
        '&amp;lt;/' $0   '&amp;gt;'
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;それからスクリプトを実行します:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ./perl6 xml-01.pl
not ok 1 - 'abc'
ok 2 - '&amp;lt;a&amp;gt;&amp;lt;/a&amp;gt;'
not ok 3 - '..&amp;lt;ab&amp;gt;foo&amp;lt;/ab&amp;gt;dd'
not ok 4 - '&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'
not ok 5 - '&amp;lt;a href="foo"&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'
not ok 6 - '&amp;lt;a empty="" &amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'
not ok 7 - '&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;c&amp;gt;&amp;lt;/c&amp;gt;&amp;lt;/a&amp;gt;'
ok 8 - '&amp;lt;'
ok 9 - '&amp;lt;a&amp;gt;b&amp;lt;/b&amp;gt;'
ok 10 - '&amp;lt;a&amp;gt;b&amp;lt;/a'
ok 11 - '&amp;lt;a&amp;gt;b&amp;lt;/a href=""&amp;gt;'
not ok 12 - '&amp;lt;a/&amp;gt;'
not ok 13 - '&amp;lt;a /&amp;gt;'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;つまりこれは一対の開始タグと終了タグのペアを解析する単純なルールであり、妥当でない4つのXMLをきちんと排除できています。&lt;/p&gt;

&lt;p&gt;1番目のテストも同様に簡単に通るように、次のコードを試して下さい:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grammar XML {
    token TOP   { ^ &amp;lt;xml&amp;gt; $ };
    token xml   { &amp;lt;text&amp;gt; | &amp;lt;tag&amp;gt; };
    token text  { &amp;lt;-[&amp;lt;&amp;gt;&amp;amp;]&amp;gt;*  };
    token tag   {
        '&amp;lt;' (\w+) '&amp;gt;'
        '&amp;lt;/' $0   '&amp;gt;'
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(&lt;code&gt;&amp;lt;-[...]&amp;gt;&lt;/code&gt;は否定形の文字クラスだったことを思い出して下さい)&lt;/p&gt;

&lt;p&gt;それから実行します:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ./perl6 xml-03.pl
ok 1 - 'abc'
not ok 2 - '&amp;lt;a&amp;gt;&amp;lt;/a&amp;gt;'
(残りはさっきと同じ)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;どうして2番目のテストは動かなくなったのでしょう? その理由はRakudoが最長トークンマッチをまだ実装しておらず、順番にマッチングを行っているからです。
&lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt;は空文字列に(つまりいつでも)マッチするので、&lt;code&gt;&amp;lt;text&amp;gt; | &amp;lt;tag&amp;gt;&lt;/code&gt;は&lt;code&gt;&amp;lt;tag&amp;gt;&lt;/code&gt;とのマッチングを試しません。選択肢の順番を入れ替えると動きます。&lt;/p&gt;

&lt;p&gt;しかし我々はプレーンテキストかタグだけを適当にマッチさせたいのではなく、両者のランダムな組合わせをマッチさせたいのでした:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;token xml   { &amp;lt;text&amp;gt; [ &amp;lt;tag&amp;gt; &amp;lt;text&amp;gt; ]*  };
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(&lt;code&gt;[...]&lt;/code&gt;はキャプチャしないグループであり、Perl5の&lt;code&gt;(?: ...)&lt;/code&gt;と同様です)&lt;/p&gt;

&lt;p&gt;いやはや驚くことに、これは最初の2つのテストを両方とも通過します。&lt;/p&gt;

&lt;p&gt;3番目のテスト&lt;code&gt;.&amp;lt;ab&amp;gt;foo&amp;lt;/ab&amp;gt;dd&lt;/code&gt;は開始タグと終了タグの間にテキストがあるので、次はこれを受理しなければいけません。
しかしタグの間に出現できるのはテキストに限らず任意のXMLで在り得るので、&lt;code&gt;&amp;lt;xml&amp;gt;&lt;/code&gt;を単に呼ぶことにしましょう:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;token tag   {
    '&amp;lt;' (\w+) '&amp;gt;'
    &amp;lt;xml&amp;gt;
    '&amp;lt;/' $0   '&amp;gt;'
}

./perl6 xml-05.pl
ok 1 - 'abc'
ok 2 - '&amp;lt;a&amp;gt;&amp;lt;/a&amp;gt;'
ok 3 - '..&amp;lt;ab&amp;gt;foo&amp;lt;/ab&amp;gt;dd'
ok 4 - '&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'
not ok 5 - '&amp;lt;a href="foo"&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'
(残りはさっきと同じ)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これで属性(&lt;code&gt;href="foo"&lt;/code&gt;のやつ)に集中することができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;token tag   {
    '&amp;lt;' (\w+) &amp;lt;attribute&amp;gt;* '&amp;gt;'
    &amp;lt;xml&amp;gt;
    '&amp;lt;/' $0   '&amp;gt;'
};
token attribute {
    \w+ '="' &amp;lt;-["&amp;lt;&amp;gt;]&amp;gt;* \"
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;しかしこれでは新しいテストを通過できるようにはなりません。その原因はタグ名と属性の間にある空白です。
&lt;code&gt;\s+&lt;/code&gt;や&lt;code&gt;\s*&lt;/code&gt;を色んな場所に加える代わりに、&lt;code&gt;token&lt;/code&gt;を&lt;code&gt;rule&lt;/code&gt;(&lt;code&gt;:sigspace&lt;/code&gt;修飾子を暗黙的にセットします)に切り替えることにします:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rule tag   {
    '&amp;lt;'(\w+) &amp;lt;attribute&amp;gt;* '&amp;gt;'
    &amp;lt;xml&amp;gt;
    '&amp;lt;/'$0'&amp;gt;'
};
token attribute {
    \w+ '="' &amp;lt;-["&amp;lt;&amp;gt;]&amp;gt;* \"
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これで残るテストは最後の2つになりました:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ok 1 - 'abc'
ok 2 - '&amp;lt;a&amp;gt;&amp;lt;/a&amp;gt;'
ok 3 - '..&amp;lt;ab&amp;gt;foo&amp;lt;/ab&amp;gt;dd'
ok 4 - '&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'
ok 5 - '&amp;lt;a href="foo"&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'
ok 6 - '&amp;lt;a empty="" &amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;'
ok 7 - '&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;c&amp;gt;&amp;lt;/c&amp;gt;&amp;lt;/a&amp;gt;'
ok 8 - '&amp;lt;'
ok 9 - '&amp;lt;a&amp;gt;b&amp;lt;/b&amp;gt;'
ok 10 - '&amp;lt;a&amp;gt;b&amp;lt;/a'
ok 11 - '&amp;lt;a&amp;gt;b&amp;lt;/a href=""&amp;gt;'
not ok 12 - '&amp;lt;a/&amp;gt;'
not ok 13 - '&amp;lt;a /&amp;gt;'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これらは&lt;code&gt;/&lt;/code&gt;で閉じられた入れ子になっていないタグを含んでいます。&lt;code&gt;rule tag&lt;/code&gt;にこれを追加するのは何の問題もありません:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rule tag   {
    '&amp;lt;'(\w+) &amp;lt;attribute&amp;gt;* [
        | '/&amp;gt;'
        | '&amp;gt;' &amp;lt;xml&amp;gt; '&amp;lt;/'$0'&amp;gt;'
    ]
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;全テストが通るようになりました。やった、はじめて作ったグラマーはちゃんと動きます。&lt;/p&gt;

&lt;h3&gt;さらなるハッキング&lt;/h3&gt;

&lt;p&gt;グラマーで遊ぶのは遊び方を読むよりずっと楽しいので、これから実装できるものの例を挙げておきます:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;amp;&lt;/code&gt;のような実体参照を含むことができるプレーンテキスト&lt;/li&gt;
&lt;li&gt;XMLタグ名が数字で開始して良いのかどうか分かりませんが、現在のグラマーはこれを許しています。必要ならXMLの仕様書を調べてグラマーを改造するのも良いでしょう&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;![CDATA[ ... ]]&amp;gt;&lt;/code&gt;を含むことができるプレーンテキスト。このXML風タグは無視され、&lt;code&gt;&amp;lt;&lt;/code&gt;のような文字はエスケープする必要がありません&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;?xml version="0.9" encoding="utf-8"?&amp;gt;&lt;/code&gt;のようなXML宣言を許容し、すべてを包含する単一のルートタグを要求する本物のXML(テストケースをいくつか修正する必要があります)&lt;/li&gt;
&lt;li&gt;マッチオブジェクト&lt;code&gt;$/&lt;/code&gt;を再帰的に走査することでXML用のプリティプリンタを実装できます(これは生半可にはいきません; いくつかRakudoのバグを回避しなければいけないかも知れませんし、キャプチャも新しく導入する必要があるかも知れません)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(解答をこのブログのコメント欄に書かないで下さい; 他の人にも楽しませてあげましょう;-)&lt;/p&gt;

&lt;p&gt;ハッキングを楽しんで下さい。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;強力だし、楽しい&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;正規表現はS05で詳細に規定されています: &lt;a href="http://perlcabal.org/syn/S05.html"&gt;http://perlcabal.org/syn/S05.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;正規表現とグラマーの動作している(!)例を、Perl6で書かれたWikiエンジンであるNovember projectでもっと見つけることができます。&lt;a href="http://github.com/viklund/november/"&gt;http://github.com/viklund/november/&lt;/a&gt;をご覧下さい。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-7570399323663723359?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/7570399323663723359/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6-xml.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7570399323663723359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7570399323663723359'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6-xml.html' title='Perl 5 to 6 - (似非)XMLのグラマー'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-7599785908937498385</id><published>2011-03-01T01:00:00.004+09:00</published><updated>2011-03-01T01:16:22.668+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 正規表現の逆襲</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/19-regex.html"&gt;"Perl 5 to 6" Lesson 19 - Regexes strike back&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 19 - 正規表現の逆襲&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;# 通常のマッチング:
if 'abc' ~~ m/../ {
    say $/;                 # ab
}

# 暗黙的な:sigspace修飾子を使ったマッチング
if 'ab cd ef'  ~~ mm/ (..) ** 2 / {
    say $1;                 # cd
}

# :sigspace修飾子を使った文字列置換
my $x = "abc     defg";
$x ~~ ss/c d/x y/;
say $x;                     # abx     yefg
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;正規表現の基本は&lt;a href="http://outer-inside.blogspot.com/2011/02/perl-5-to-6_18.html"&gt;Lesson 07&lt;/a&gt;で既に述べたので、役に立つ(が体系立っていない)内容をいくらか補足します。&lt;/p&gt;

&lt;h3&gt;マッチング&lt;/h3&gt;

&lt;p&gt;正規表現マッチングのためにグラマーを書かないといけない訳ではなく、昔ながらの&lt;code&gt;m/.../&lt;/code&gt;はまだ動きます。
新しい兄弟分として&lt;code&gt;mm/.../&lt;/code&gt;形式があり、&lt;code&gt;:sigspace&lt;/code&gt;修飾子を暗黙的に有効にします。これは正規表現中の空白を&lt;code&gt;&amp;lt;.ws&amp;gt;&lt;/code&gt;ルールで置換するものだったことを思い出して下さい。&lt;/p&gt;

&lt;p&gt;このルールのデフォルトは、2つの単語文字で囲まれている(つまりそれぞれが&lt;code&gt;\w&lt;/code&gt;にマッチする)場合は&lt;code&gt;\s+&lt;/code&gt;にマッチし、さもなくば&lt;code&gt;\s*&lt;/code&gt;にマッチします。&lt;/p&gt;

&lt;p&gt;文字列置換において&lt;code&gt;:samespace&lt;/code&gt;修飾子は&lt;code&gt;&amp;lt;ws&amp;gt;&lt;/code&gt;ルールにマッチした空白を保存します。
同様に&lt;code&gt;:samecase&lt;/code&gt;及び短縮形の&lt;code&gt;:ii&lt;/code&gt;(&lt;code&gt;:i&lt;/code&gt;の親戚だからです)修飾子は大文字小文字の違いを保存します。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $x = 'Abcd';
$x ~~ s:ii/^../foo/;
say $x;                     # Foocd
$x = 'ABC'
$x ~~ s:ii/^../foo/;
say $x                      # FOO
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これはモジュール&lt;code&gt;Foo&lt;/code&gt;をすべて&lt;code&gt;Bar&lt;/code&gt;に改名したいけれど、例えば環境変数がすべて大文字で書かれているときに非常に便利です。&lt;code&gt;:ii&lt;/code&gt;修飾子が大文字小文字の違いを自動で保存してくれます。&lt;/p&gt;

&lt;p&gt;これは大文字か小文字かという情報を文字毎にコピーしますが、より頭の良いバージョンもあります; &lt;code&gt;:sigspace&lt;/code&gt;(短縮形は&lt;code&gt;:s&lt;/code&gt;)修飾子と一緒に使うと、大文字小文字のパターンをソース文字列から探します。
&lt;code&gt;.lc&lt;/code&gt;、&lt;code&gt;.uc&lt;/code&gt;、&lt;code&gt;.lc.ucfirst&lt;/code&gt;、&lt;code&gt;uc.lcfirst&lt;/code&gt;、&lt;code&gt;lc.capitalize&lt;/code&gt;(&lt;code&gt;Str.capitalize&lt;/code&gt;は各単語の最初の文字を大文字にするメソッド)が認識されます。このようなパターンを見つけると置換後の文字列にも適用します。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $x = 'The Quick Brown Fox';
$x ~~ s :s :ii /brown.*/perl 6 developer/;
# $xは'The Quick Perl 6 Developer'
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;選択肢&lt;/h3&gt;

&lt;p&gt;選択肢は相変わらず&lt;code&gt;|&lt;/code&gt;で表現されますが、Perl5とは違った意味になります。
選択肢を順番にマッチングしていって最初にマッチしたものを取るのではなく、全選択肢を並列にマッチングして最長一致のものを取ります。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'aaaa' ~~ m/ a | aaa | aa /;
say $/                          # aaa
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;つまらない変更に見えるかも知れませんがこれは広範囲に影響し、また拡張性のあるグラマーにとって極めて重要です。
Perl6はグラマーを使って解析されるので、&lt;code&gt;++$a&lt;/code&gt;の&lt;code&gt;++&lt;/code&gt;が2つの&lt;code&gt;prefix:&amp;lt;+&amp;gt;&lt;/code&gt;トークンではなく1つのトークンとして解析されるのはこのためです。&lt;/p&gt;

&lt;p&gt;順番にマッチングする古い方式は&lt;code&gt;||&lt;/code&gt;で利用できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grammar Math::Expression {
    token value {
        | &amp;lt;number&amp;gt;
        | '(' 
          &amp;lt;expression&amp;gt; 
          [ ')' || { fail("Parenthesis not closed") } ]
    }
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;{ ... }&lt;/code&gt;はクロージャを実行し、その中での&lt;code&gt;fail&lt;/code&gt;の呼び出しは式を失敗させます。
この枝は前のマッチング(ここでは')')が失敗したときだけ呼び出されることが保証されているので、解析中に役立つエラーメッセージを出すのに使えます。&lt;/p&gt;

&lt;p&gt;選択肢を書く方法は他にもあり、例えば配列を「展開」すると要素の選択肢としてマッチさせることができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$_ = '12 oranges';
my @fruits = &amp;lt;apple organge banana kiwi&amp;gt;;
if m:i:s/ (\d+) (@fruits)s? / {
    say "You've got $0 $1, I've got { $0 + 2 } of them. You lost.";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;自動的に最長一致にマッチする選択肢の構築方法がもう1つあります: 多重正規表現です。
これは&lt;code&gt;multi token name&lt;/code&gt;のように書かれるか、&lt;code&gt;proto&lt;/code&gt;を使って次のように書かれます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grammar Perl {
    ...
    proto token sigil { ... }
    token sigil:sym&amp;lt;$&amp;gt; { &amp;lt;sym&amp;gt; }
    token sigil:sym&amp;lt;@&amp;gt; { &amp;lt;sym&amp;gt; }
    token sigil:sym&amp;lt;%&amp;gt; { &amp;lt;sym&amp;gt; }
    ...
    token variable { &amp;lt;sigil&amp;gt; &amp;lt;twigil&amp;gt;? &amp;lt;identifier&amp;gt; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;この例は&lt;code&gt;sigil&lt;/code&gt;という多重トークンを表しており、これは&lt;code&gt;sym&lt;/code&gt;でパラメータ化されています。
短い名前、つまり&lt;code&gt;sigil&lt;/code&gt;が使われた場合は全トークンを選択肢としてマッチします。
選択肢を書くのにこれは非常に面倒くさいと思うかも知れませんが、これには&lt;code&gt;'$'|'@'|'%'&lt;/code&gt;と書くのに比べてとても大きな利点があります: 多重正規表現は容易に拡張可能です。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grammar AddASigil is Perl {
    token sigil:sym&amp;lt;!&amp;gt; { &amp;lt;sym&amp;gt; }
}
# わあ、新しいシジルを持ったPerl6グラマーができたぞ!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;さらに、既存の選択肢を上書きすることもできます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grammar WeirdSigil is Perl {
    token sigil:sym&amp;lt;$&amp;gt; { '°' }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;このグラマーではスカラーのシジルは&lt;code&gt;°&lt;/code&gt;なので、このグラマーはシジルを探すときは毎回&lt;code&gt;$&lt;/code&gt;の代わりに&lt;code&gt;°&lt;/code&gt;を探索しますが、コンパイラにはそれにマッチした正規表現が&lt;code&gt;sigil:sym&amp;lt;$&amp;gt;&lt;/code&gt;であることが分かります。&lt;/p&gt;

&lt;p&gt;次のレッスンでは実際の、Rakudoで動作するグラマーをお見せしましょう。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-7599785908937498385?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/7599785908937498385/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7599785908937498385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7599785908937498385'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/03/perl-5-to-6.html' title='Perl 5 to 6 - 正規表現の逆襲'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-148665174793320207</id><published>2011-02-27T23:53:00.003+09:00</published><updated>2011-02-28T09:51:13.200+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - スコープ</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/18-scoping.html"&gt;"Perl 5 to 6" Lesson 18 - Scoping&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 18 - Scoping&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;for 1 .. 10 -&amp;gt; $a {
    # ここは$aが見える
}
# ここは$aが見えない

while my $b = get_stuff() {
    # ここは$bが見える
}
# ここでも$bが見える

my $c = 5;
{
    my $c = $c;
    # ここで$cがundefになる
}
# ここでは$cは5

my $y;
my $x = $y + 2 while $y = calc();
# まだ$xが見える
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;h3&gt;字句的スコープ&lt;/h3&gt;

&lt;p&gt;Perl6のスコープはPerl5に非常によく似ています。ブロックは新しい字句的スコープを導入します。
変数名は最も内側の字句的スコープから探索され、もし見つからなければ一つ外側のスコープを、といった手順で探索されます。
Perl5と同様に&lt;code&gt;my&lt;/code&gt;変数は完全な字句的スコープ変数であり、&lt;code&gt;our&lt;/code&gt;宣言はパッケージ変数に字句的スコープを持った別名を作ります。&lt;/p&gt;

&lt;p&gt;ただしちょっとした違いがあります: 変数はブロックの宣言された位置より後で可視であり、ブロックのヘッダ(例えば&lt;code&gt;while&lt;/code&gt;ループの条件節など)で宣言された変数はブロック内に限定されません。&lt;/p&gt;

&lt;p&gt;スコープを限定したいときはブロックの形式的パラメータが使えます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if calc() -&amp;gt; $result {
    # ここでは$resultが使える
}
# ここでは$resultが見えない
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;変数は宣言の直後から可視であり、Perl5のように文の終わりからではありません。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $x = .... ;
        ^^^^^
        Perl6では$xは可視だが、Perl5では不可視
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;動的スコープ&lt;/h3&gt;

&lt;p&gt;形容詞&lt;code&gt;local&lt;/code&gt;は&lt;code&gt;temp&lt;/code&gt;という名前になり、初期値が与えられないときは(&lt;code&gt;undef&lt;/code&gt;ではなく)以前の値を使うようになりました。&lt;/p&gt;

&lt;p&gt;また不確定(hypothetical)変数と呼ばれる新しい動的スコープ変数もあります。
これは例外によってブロックから抜けた場合には以前の値を復元し、そうでない場合には値を保持します。&lt;/p&gt;

&lt;h3&gt;コンテキスト変数&lt;/h3&gt;

&lt;p&gt;Perl5でグローバルだったいくつかの変数(&lt;code&gt;$!&lt;/code&gt;、&lt;code&gt;$_&lt;/code&gt;)はPerl6ではコンテキスト変数になりました。
これは動的スコープ間で受け渡しされます。&lt;/p&gt;

&lt;p&gt;これは昔からあるPerl5の問題を解決します。Perl5ではブロックを抜ける際に&lt;code&gt;DESTROY&lt;/code&gt;サブルーチンが呼ばれることがあり、意図せずしてグローバル変数の値を変更してしまうことがありました。例えばエラー変数です:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# 壊れたPerl5コード
sub DESTROY { eval { 1 }; }

eval {
    my $x = bless {};
    die "Death\n";
};
print $@ if $@;         # 何も出力されない
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perl6ではグローバル変数の暗黙的な使用がないのでこの問題は回避されます。&lt;/p&gt;

&lt;p&gt;(Perl5.14では&lt;code&gt;$@&lt;/code&gt;を変更から保護しようとしており、この例にある問題のほとんどは回避されます)&lt;/p&gt;

&lt;h3&gt;疑似パッケージ&lt;/h3&gt;

&lt;p&gt;変数が同名の字句的スコープ変数で隠されているときは、&lt;code&gt;OUTER&lt;/code&gt;疑似パッケージを使ってアクセスすることができます&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $x = 3;
{
    my $x = 10;
    say $x;             # 10
    say $OUTER::x;      # 3
    say OUTER::&amp;lt;$x&amp;gt;     # 3
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;同様に関数も&lt;code&gt;CALLER&lt;/code&gt;や&lt;code&gt;CONTEXT&lt;/code&gt;疑似パッケージから呼び出し元の変数にアクセスすることができます。
これらの違いは&lt;code&gt;CALLER&lt;/code&gt;が直前の呼び出し元の変数のみにアクセスするのに対して、&lt;code&gt;CONTEXT&lt;/code&gt;はUNIXの環境変数のようにはたらきます(コンパイラの内部で&lt;code&gt;$_&lt;/code&gt;や&lt;code&gt;$!&lt;/code&gt;のような変数を扱うためにだけ使うべきです)。
外部の動的スコープから変数にアクセスするためには、変数が&lt;code&gt;is context&lt;/code&gt;として宣言されていなければなりません。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;グローバル変数が本当に悪であり、幾多の問題の温床であることは今日では広く知られています。
我々はより良いスコープ機構を実装するためのリソースを持っているので、グローバル変数は本質的にグローバルであるデータ(&lt;code&gt;%*ENV&lt;/code&gt;や&lt;code&gt;$*PID&lt;/code&gt;のような)にのみ使われています。&lt;/p&gt;

&lt;p&gt;ブロックスコープの規則は非常に単純化されました。&lt;/p&gt;

&lt;p&gt;Perl5の&lt;code&gt;perlsyn&lt;/code&gt;ドキュメントを引用しておきます; Perl6で同じことは望みません:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;注意: 条件ないしループ文修飾子で修飾された"my"文(例えば"my $x if ...")の挙動は
未定義である。"my"変数の値はundefかも知れないし、以前に代入された値であったり、
あるいはそれ以外の何かかも知れない。挙動を信用してはいけない。将来のバージョンのPerl
では今使っているPerlと異なった挙動を示すかも知れない。ここには竜が潜んでいる。
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;S04にブロックスコープの議論があります: &lt;a href="http://perlcabal.org/syn/S04.html"&gt;http://perlcabal.org/syn/S04.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;S02に疑似パッケージの全リストとコンテキストスコープの説明があります: &lt;a href="http://perlcabal.org/syn/S02.html#Names"&gt;http://perlcabal.org/syn/S02.html#Names&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-148665174793320207?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/148665174793320207/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_27.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/148665174793320207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/148665174793320207'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_27.html' title='Perl 5 to 6 - スコープ'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-6966989916863057238</id><published>2011-02-26T22:41:00.004+09:00</published><updated>2011-02-27T02:08:58.066+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - Unicode</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/17-unicode.html"&gt;"Perl 5 to 6" Lesson 17 - Unicode&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 17 - Unicode&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;(なし)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Perl5のUnicodeモデルは大きな弱点に悩んでいました: バイナリとテキストデータに同じ型を使っていたのです。
プログラムがネットワークソケットから512バイト読み込んだとすると、それは当然バイト列になります。しかしそれに対して(Perl5で)&lt;code&gt;uc&lt;/code&gt;を呼ぶとテキストとして扱われます。
推奨されている方法は最初にバイト列をデコードすることですが、サブルーチンがそれを引数として受け取る段階では、それがエンコードされているのかどうか、つまりblobとして扱うべきかテキストとして扱うべきか確実に判断することは不可能です。&lt;/p&gt;

&lt;p&gt;一方、Perl6は単なるバイトのコレクションである&lt;code&gt;Buf&lt;/code&gt;型を提供します。また&lt;code&gt;Str&lt;/code&gt;は論理的な文字のコレクションです。&lt;/p&gt;

&lt;p&gt;論理的な文字という用語にはいささか説明が必要です。正確に言うと、&lt;code&gt;Str&lt;/code&gt;は様々な水準の見方ができるオブジェクトです: &lt;code&gt;Byte&lt;/code&gt;、&lt;code&gt;CodePoint&lt;/code&gt;(Unicodeコンソーシアムが番号を割り当てたものすべて)、&lt;code&gt;Grapheme&lt;/code&gt;(書記素; 文字として目に見えるもの)、&lt;code&gt;CharLingua&lt;/code&gt;(言語定義文字)。&lt;/p&gt;

&lt;p&gt;例えば16進数表記で&lt;code&gt;61 cc 80&lt;/code&gt;は(当然)3バイトのバイト列を構成します。しかしこれは2つのコードポイント&lt;code&gt;LATIN SMALL LETTER A&lt;/code&gt;(U+0041)と&lt;code&gt;COMBINING GRAVE ACCENT&lt;/code&gt;(U+0300)、あるいは1つの書記素(ブログシステムないしあなたのブラウザが文字を殺してなければ、&lt;code&gt;à&lt;/code&gt;のように見えます)を表しているものと見ることもできます。&lt;/p&gt;

&lt;p&gt;したがって文字列の長さを単純に調べることはできず、特定の見方に拠る長さを調べる必要があります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$str.bytes;
$str.codes;
$str.graphs;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;chars&lt;/code&gt;メソッドもあり、これは現在のUnicode水準(&lt;code&gt;use byte&lt;/code&gt;のようなプラグマで指定でき、デフォルトは書記素)における長さを返します。&lt;/p&gt;

&lt;p&gt;Perl5ではしばしば間違ってバイト列を文字列に連結してしまう問題が起きます。
Perl6でそのような問題に悩んだときは、文字列連結演算子をオーバーロードして簡単に問題が発生した位置を特定できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub GLOBAL::infix:&amp;lt;~&amp;gt; is deep (Str $a, Buf $b)|(Buf $b, Str $a) {
    die "Can't concatenate text string «"
        ~ $a.encode("UTF-8")
          "» with byte string «$b»\n";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;エンコードとデコード&lt;/h3&gt;

&lt;p&gt;IOシステムの仕様は非常に基本的なもので、エンコードとデコード用のレイヤはまだ定義されていません。この記事にSYNOPSISがないのはそのためです。
そのような機構が用意されるのは間違いなく、コードは次のようなものになると思われます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $handle = open($filename, :r, :encoding&amp;lt;UTF-8&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;正規表現とUnicode&lt;/h3&gt;

&lt;p&gt;正規表現はUnicode水準を指定する修飾子を取ることができ、&lt;code&gt;m:codes/./&lt;/code&gt;は丁度1個のコードポイントにマッチします。修飾子を指定しない場合は現在のUnicde水準が使われます。&lt;/p&gt;

&lt;p&gt;(文字にマッチする)&lt;code&gt;\w&lt;/code&gt;のような文字クラスはUnicode標準にしたがって動作します。
修飾子として大文字小文字の無視(&lt;code&gt;:i&lt;/code&gt;)やアクセントの無視(&lt;code&gt;:a&lt;/code&gt;)、置換演算子の置換結果に大文字小文字やアクセントを反映するもの(&lt;code&gt;:samecase&lt;/code&gt;と&lt;code&gt;:sameaccent&lt;/code&gt;、省略形は&lt;code&gt;:ii&lt;/code&gt;と&lt;code&gt;:aa&lt;/code&gt;)があります。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;今日のほとんどのツールやプログラミング言語で文字列を正しく処理するのはとても難しいことです。
Perl5で書かれたWebアプリケーションを作っているとして、長い単語がレイアウトを崩してしまわないように分割したいとしましょう。
組み込みの&lt;code&gt;substr&lt;/code&gt;を使ったりすると、意図せずして書記素が泣き別れになるかも知れません。&lt;/p&gt;

&lt;p&gt;Perl6は書記素レベルの文字列操作を組み込みでサポートした最初の主要言語になります。
この文字列操作機能はUnicodeを使う上でほとんどの悩みを取払い、(正規表現と連携して)Perl6を文字列処理における最も強力な言語の1つにします。&lt;/p&gt;

&lt;p&gt;テキスト用とバイト列用の個別のデータ型はデバッグとイントロスペクションを非常に容易にします。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S29.html#Str"&gt;http://perlcabal.org/syn/S29.html#Str&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-6966989916863057238?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/6966989916863057238/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6-unicode.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6966989916863057238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6966989916863057238'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6-unicode.html' title='Perl 5 to 6 - Unicode'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-281016029073579264</id><published>2011-02-26T14:41:00.001+09:00</published><updated>2011-02-26T14:43:32.093+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 列挙型</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/16-enums.html"&gt;"Perl 5 to 6" Lesson 16 - Enums&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 16 - 列挙型&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;enum bit Bool &amp;lt;False True&amp;gt;;
my $value = $arbitrary_value but True;
if $value {
    say "Yes, it's true";       # 表示される
}

enum Day ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');
if custom_get_date().Day == Day::Sat | Day::Sun {
    say "Weekend";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;列挙型は用途の広い獣です。定数の列挙からなる低レベルのクラスであり、定数は典型的には整数や文字列です(が任意のものが使えます)。&lt;/p&gt;

&lt;p&gt;これらの定数は派生型やメソッド、あるいは通常の値のようにふるまいます。
&lt;code&gt;but&lt;/code&gt;演算子でオブジェクトに結びつけることができ、これによって列挙型を値に「ミックスイン」できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $x = $today but Day::Tue;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;列挙型の型名を関数のように使うこともでき、引数として値を指定できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$x = $today but Day($weekday);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;こうするとオブジェクトは列挙型の名前(ここでは&lt;code&gt;Day&lt;/code&gt;)をメソッド名として持ちます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say $x.Day;             # 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;最初の定数の値は&lt;code&gt;0&lt;/code&gt;、その次は&lt;code&gt;1&lt;/code&gt;と続きます。ただしペア記法を使って明示的に別の値を指定した場合は別です:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Enum Hackers (:Larry&amp;lt;Perl&amp;gt;, :Guido&amp;lt;Python&amp;gt;, :Paul&amp;lt;Lisp&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ある値がミックスインされているかどうかはスマートマッチ演算子や&lt;code&gt;.does&lt;/code&gt;メソッドで調べることができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if $today ~~ Day::Fri {
    say "Thank Christ it's Friday"
}
if $today.does(Fri) { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;曖昧性がない場合、(&lt;code&gt;Fri&lt;/code&gt;のように)値の名前だけを与えれば良いことを覚えておいて下さい。
曖昧な場合は完全な名前である&lt;code&gt;Day::Fri&lt;/code&gt;を与える必要があります。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;列挙型はPerl5の汚染変数に関する「マジック」と(数値として使われた時に警告が出ないよう特別扱いされている)&lt;code&gt;"0 but true"&lt;/code&gt;を返すハックの両方を代替します。加えて真理値(&lt;code&gt;Bool&lt;/code&gt;)型も提供します。&lt;/p&gt;

&lt;p&gt;列挙型はデバッグやトレースのために任意のメタデータを付加する柔軟性と能力をも提供します。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S12.html#Enums"&gt;http://perlcabal.org/syn/S12.html#Enums&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-281016029073579264?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/281016029073579264/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_1128.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/281016029073579264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/281016029073579264'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_1128.html' title='Perl 5 to 6 - 列挙型'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-6442097572392376157</id><published>2011-02-26T01:40:00.003+09:00</published><updated>2011-02-27T01:33:07.556+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - ツイジル</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/15-twigils.html"&gt;"Perl 5 to 6" Lesson 15 - Twigils&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 15 - ツイジル&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;class Foo {
    has $.bar;
    has $!baz;
}

my @stuff = sort { $^b[1] &amp;lt;=&amp;gt; $^a[1]}, [1, 2], [0, 3], [4, 8];
my $block = { say "This is the named 'foo' parameter: $:foo" };
$block(:foo&amp;lt;bar&amp;gt;);

say "This is file $?FILE on line $?LINE"

say "A CGI script" if %*ENV.exists('DOCUMENT_ROOT');
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;いくつかの変数にはツイジルという第2のシジルがあります。これは基本的にはその変数が「普通」ではないということです。違いはいくつかあり、例えばスコープの違いなどです。&lt;/p&gt;

&lt;p&gt;オブジェクトのパブリックな属性とプライベートな属性がそれぞれ&lt;code&gt;.&lt;/code&gt;と&lt;code&gt;!&lt;/code&gt;というツイジルを持つことは既に紹介しました; それらは通常の変数ではなく&lt;code&gt;self&lt;/code&gt;に結びつけられています。&lt;/p&gt;

&lt;p&gt;ツイジル&lt;code&gt;^&lt;/code&gt;はPerl5で例外的に扱われていたケースを一般化します。次のように書けます&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# 注意: Perl5のコードです
sort { $a &amp;lt;=&amp;gt; $b } @array
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;$a&lt;/code&gt;と&lt;code&gt;$b&lt;/code&gt;は&lt;code&gt;strict&lt;/code&gt;プラグマに特別扱いされていました。Perl6には自己宣言された位置的パラメータというコンセプトがあり、このパラメータがツイジル&lt;code&gt;^&lt;/code&gt;を持ちます。
これはブロックのシグネチャリストに書かれない位置的パラメータで、辞書順(アルファベット順)に引数を割り当てられます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $block = { say "$^c $^a $^b" };
$block(1, 2, 3);                # 3 1 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;したがってこのように書けます&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@list = sort { $^b &amp;lt;=&amp;gt; $^a }, @list;
# あるいは:
@list = sort { $^foo &amp;lt;=&amp;gt; $^bar }, @list;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;どこにも特別扱いはありません。&lt;/p&gt;

&lt;p&gt;位置的引数と名前付き引数の対称性を保つため、ツイジル&lt;code&gt;:&lt;/code&gt;が名前付きパラメータに対して同様に働きます。
したがって次の2行はほぼ等価です:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $block = { say $:stuff }
my $sub   = sub (:$stuff) { say $stuff }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ツイジル&lt;code&gt;?&lt;/code&gt;は変数や定数がコンパイル時に確定できることを意味します。
例えば&lt;code&gt;$?LINE&lt;/code&gt;は現在の行番号(以前は&lt;code&gt;__LINE__&lt;/code&gt;でした)であり、&lt;code&gt;$?DATA&lt;/code&gt;は&lt;code&gt;DATA&lt;/code&gt;セクションのファイルハンドルです。&lt;/p&gt;

&lt;p&gt;コンテキスト変数にはツイジル&lt;code&gt;*&lt;/code&gt;でアクセスできます。なので&lt;code&gt;$*IN&lt;/code&gt;や&lt;code&gt;$*OUT&lt;/code&gt;は動的に上書きできます。&lt;/p&gt;

&lt;p&gt;疑似ツイジルとして&lt;code&gt;&amp;lt;&lt;/code&gt;があり、&lt;code&gt;$&amp;lt;capture&amp;gt;&lt;/code&gt;のように使われます。これは正規表現マッチオブジェクトにアクセスする&lt;code&gt;$/&amp;lt;capture&amp;gt;&lt;/code&gt;の省略記法です。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;Perl5の&lt;code&gt;perlvar&lt;/code&gt;ドキュメントを読めば、膨大な数の変数があることが分かります。
それらの多くはグローバル変数で、プログラムに与える影響も様々です。&lt;/p&gt;

&lt;p&gt;ツイジルはそれら特殊変数にある程度の秩序を与える試みであり、また一方で特別扱いされる部分を減らします。
オブジェクトの属性の場合は&lt;code&gt;self.var&lt;/code&gt;を&lt;code&gt;$.var&lt;/code&gt;(とか&lt;code&gt;@.var&lt;/code&gt;とかなんとか)と略記できるようにします。&lt;/p&gt;

&lt;p&gt;つまるところ、悪化した「句読点ノイズ」はプログラムをよりいっそう一貫性ある、読み易いものにします。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-6442097572392376157?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/6442097572392376157/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_26.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6442097572392376157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6442097572392376157'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_26.html' title='Perl 5 to 6 - ツイジル'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5479286237417609841</id><published>2011-02-26T00:06:00.004+09:00</published><updated>2011-02-26T00:17:23.854+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - MAINサブルーチン</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/14-main-sub.html"&gt;"Perl 5 to 6" Lesson 14 - The MAIN sub&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 14 - MAINサブルーチン&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;# ファイル doit.pl

#!/usr/bin/perl6
sub MAIN($path, :$force, :$recursive, :$home = '~/') {
    # do stuff here
}

# コマンドライン
$ ./doit.pl --force --home=/home/someoneelse file_to_process
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;サブルーチン呼び出しと典型的なUNIXプログラムのコマンドラインからの起動は、見た目にはとてもよく似ています: 位置的な引数やオプション、名前付き引数を与えられます。&lt;/p&gt;

&lt;p&gt;この類似点のおかげで、Perl6はコマンドラインを処理してサブルーチン呼び出しに変換してくれます。
スクリプトは通常通り実行され(この時点で&lt;code&gt;@*ARGS&lt;/code&gt;に格納されているコマンドライン引数を書き換えることもできます)、その後もし存在すれば&lt;code&gt;MAIN&lt;/code&gt;サブルーチンが呼び出されます。&lt;/p&gt;

&lt;p&gt;コマンドライン引数が&lt;code&gt;MAIN&lt;/code&gt;サブルーチンの形式的パラメータにマッチしない場合、自動的に生成されたUsageが表示されます。&lt;/p&gt;

&lt;p&gt;コマンドラインオプションはサブルーチン引数に以下のようにマップされます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-name                   :name
-name=value             :name&amp;lt;value&amp;gt;

# &amp;lt;...&amp;gt;はqw(...)のようなものでしたね
--hackers=Larry,Damian  :hackers&amp;lt;Larry Damian&amp;gt;  

--good_language         :good_language
--good_lang=Perl        :good_lang&amp;lt;Perl&amp;gt;
--bad_lang PHP          :bad_lang&amp;lt;PHP&amp;gt;

+stuff                  :!stuff
+stuff=healty           :stuff&amp;lt;healthy&amp;gt; but False
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;$x = $obj but False&lt;/code&gt;は&lt;code&gt;$x&lt;/code&gt;が&lt;code&gt;$obj&lt;/code&gt;のコピーではあるけれど、真理値コンテキストでは&lt;code&gt;Bool::False&lt;/code&gt;になるという意味です。&lt;/p&gt;

&lt;p&gt;これによって、単純な(そしていくつかの単純でない)ケースでは外部のコマンドライン解析器は必要なくなり、単に&lt;code&gt;MAIN&lt;/code&gt;を使えば良くなりました。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;この背景にある動機は極めて明確です: 簡単なことは容易に、よく似たことは同様に、そしてほとんどのコマンドライン処理を一行(&lt;code&gt;MAIN&lt;/code&gt;のシグネチャ)に。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S06.html#Declaring_a_MAIN_subroutine"&gt;http://perlcabal.org/syn/S06.html#Declaring_a_MAIN_subroutine&lt;/a&gt;に仕様があります。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5479286237417609841?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5479286237417609841/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6-main.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5479286237417609841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5479286237417609841'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6-main.html' title='Perl 5 to 6 - MAINサブルーチン'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-6466202774278444936</id><published>2011-02-25T16:19:00.003+09:00</published><updated>2011-02-25T16:49:54.222+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - カスタム演算子</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/13-custom-operators.html"&gt;"Perl 5 to 6" Lesson 13 - Custom Operators&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 13 - カスタム演算子&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;multi sub postfix:&amp;lt;!&amp;gt;(Int $x) {
    my $factorial = 1;
    $factorial *= $_ for 2..$x;
    return $factorial;
}

say 5!;                     # 120
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;演算子は変わった名前を持ち、優先度とか結合性のような付加的な属性が少しだけ付いた関数です。
Perl6は通常&lt;code&gt;term infix term&lt;/code&gt;というパターンに従います。&lt;code&gt;term&lt;/code&gt;は前置演算子が前に付いていたり、後置演算子や後置接周(postcircumfix)演算子が後に付いたりしていても構いません。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1 + 1               中置
+1                  前置
$x++                後置
&amp;lt;a b c&amp;gt;             接周
@a[1]               後置接周
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;演算子の名前は「特別な」文字に限らず、空白以外なら何でも使えます。&lt;/p&gt;

&lt;p&gt;演算子の長い名前はそのタイプの後にコロンとリテラルあるいはシンボルのリストが付きます。
例えば&lt;code&gt;infix:&amp;lt;+&amp;gt;&lt;/code&gt;は&lt;code&gt;1+2&lt;/code&gt;で使われている演算子です。
もう一つの例は&lt;code&gt;postcircumfix:&amp;lt;[ ]&amp;gt;&lt;/code&gt;で、これは&lt;code&gt;@a[0]&lt;/code&gt;の演算子です。&lt;/p&gt;

&lt;p&gt;これまで得た知識を使えば、もう新しい演算子を定義できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi sub prefix:&amp;lt;€&amp;gt; (Str $x) {
    2 *  $x;
}
say €4;                         # 8
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;優先度&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$a + $b * $c&lt;/code&gt;のような式において、&lt;code&gt;infix:&amp;lt;*&amp;gt;&lt;/code&gt;演算子は&lt;code&gt;infix:&amp;lt;+&amp;gt;&lt;/code&gt;演算子よりきつい優先度を持ちます。
これが式が&lt;code&gt;$a + ($b * $c)&lt;/code&gt;と解釈される理由です。&lt;/p&gt;

&lt;p&gt;新しい演算子の優先度は既存の演算子との比較で与えることができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi sub infix:&amp;lt;foo&amp;gt; is equiv(&amp;amp;infix:&amp;lt;+&amp;gt;) { ...  }
mutli sub infix:&amp;lt;bar&amp;gt; is tighter(&amp;amp;infix:&amp;lt;+&amp;gt;) { ... }
mutli sub infix:&amp;lt;baz&amp;gt; is looser(&amp;amp;infix:&amp;lt;+&amp;gt;) { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;結合性&lt;/h3&gt;

&lt;p&gt;ほとんどの中置演算子は引数を2つだけ取ります。&lt;code&gt;1 / 2 / 4&lt;/code&gt;のような式では、評価の順序は結合性に拠って決められます。
&lt;code&gt;infix:&amp;lt;/&amp;gt;&lt;/code&gt;演算子は左結合なので、この式は&lt;code&gt;(1 / 2) / 4&lt;/code&gt;と解析されます。
&lt;code&gt;infix:&amp;lt;**&amp;gt;&lt;/code&gt;(べき乗)のように右結合の演算子の場合、&lt;code&gt;2 ** 2 ** 4&lt;/code&gt;は&lt;code&gt;2 ** (2 ** 4)&lt;/code&gt;と解析されます。&lt;/p&gt;

&lt;p&gt;Perl6には更に多くの結合性があります: &lt;code&gt;none&lt;/code&gt;は同じ優先度の演算子の結合を禁止します(例えば&lt;code&gt;2 &amp;lt;=&amp;gt; 3 &amp;lt;=&amp;gt; 4&lt;/code&gt;は禁止されています)。
また&lt;code&gt;infix:&amp;lt;,&amp;gt;&lt;/code&gt;はリスト結合性を持ちます。&lt;code&gt;1, 2, 3&lt;/code&gt;は&lt;code&gt;infix:&amp;lt;,&amp;gt;(1; 2; 3)&lt;/code&gt;と解釈されます。
最後に連結結合性があります: &lt;code&gt;$a &amp;lt; $b &amp;lt; $c&lt;/code&gt;は&lt;code&gt;($a &amp;lt; $b) &amp;amp;&amp;amp; ($b &amp;lt; $c)&lt;/code&gt;と解釈されます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi sub infix:&amp;lt;foo&amp;gt; is tighter(&amp;amp;infix:&amp;lt;+&amp;gt;)
                      is assoc('left')
                      ($a, $b) {
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;後置接周と接周&lt;/h3&gt;

&lt;p&gt;後置接周演算子はメソッド呼び出しです:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class OrderedHash is Hash {
    method postcircumfix:&amp;lt;{ }&amp;gt;(Str $key) {
        ...
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;$object[$stuff]&lt;/code&gt;のようにして呼び出すと&lt;code&gt;$stuff&lt;/code&gt;がメソッドの引数として渡され、&lt;code&gt;$object&lt;/code&gt;は&lt;code&gt;self&lt;/code&gt;として参照可能になります。&lt;/p&gt;

&lt;p&gt;接周演算子は通常と違った構文(&lt;code&gt;my @list = &amp;lt;a b c&amp;gt;;&lt;/code&gt;のような)に使われることが多いのでマクロとして実装されています:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;macro circumfix:«&amp;lt; &amp;gt;»($text) is parsed / &amp;lt;-[&amp;gt;]&amp;gt;+ / {
    return $text.comb(rx/\S+/);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;is parsed&lt;/code&gt;トレイトには区切り子の中の文字列を解析する正規表現を与えます。もし指定しない場合は通常のPerl6コードとして解析されます(新しい構文を導入したいときには、これは望む動作ではないでしょう)。
&lt;code&gt;Str.comb&lt;/code&gt;はパターンを探し、マッチしたテキストのリストを返します。&lt;/p&gt;

&lt;h3&gt;既存の演算子の「オーバーロード」&lt;/h3&gt;

&lt;p&gt;(全部ではないにしろ)既存のほとんどの演算子は多重サブルーチンかメソッドであり、新しい型に合わせてカスタマイズできます。
多重サブルーチンを追加することで演算子の「オーバーロード」が実現されます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class MyStr { ... }
multi sub infix:&amp;lt;~&amp;gt;(MyStr $this, Str $other) { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これは組み込みの「特別な」オブジェクト(&lt;code&gt;Str&lt;/code&gt;や&lt;code&gt;Int&lt;/code&gt;など)のようにふるまうオブジェクトを書けるということです。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;ユーザによる新しい演算子の定義や、既存の演算子の「オーバーロード」を許すことは、ユーザ定義型を組み込み型と同じくらい強力で便利なものにします。
もし組み込み型では機能不足になったとしても、コンパイラに変更を加えることなく新しい型に置き換えて状況に対応できます。&lt;/p&gt;

&lt;p&gt;これは言語を使うことと言語を改変することのギャップをも取り払います。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S06.html#Operator_overloading"&gt;http://perlcabal.org/syn/S06.html#Operator_overloading&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;もし技術的な背景(Perl6がこのような演算子その他の変更をどうやって実現しているかなど)に興味があるなら、&lt;a href="http://perlgeek.de/en/article/mutable-grammar-for-perl-6"&gt;http://perlgeek.de/en/article/mutable-grammar-for-perl-6&lt;/a&gt;を読んで下さい。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-6466202774278444936?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/6466202774278444936/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_25.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6466202774278444936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6466202774278444936'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_25.html' title='Perl 5 to 6 - カスタム演算子'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-1262710309421605661</id><published>2011-02-23T00:07:00.004+09:00</published><updated>2011-03-07T01:23:24.958+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 遅延性</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/12-lazyness.html"&gt;"Perl 5 to 6" Lesson 12 - Laziness&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 12 - 遅延性&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;my @integers = 0..*;
for @integers -&amp;gt; $i {
    say $i;
    last if $i % 17 == 0;
}

my @even := map { 2 * $_ }, 0..*;
my @stuff := gather {
    for 0 .. Inf {
        take 2 ** $_;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Perlプログラマは怠けがちです。彼らが使うリストも。&lt;/p&gt;

&lt;p&gt;ここで怠惰という言葉が意味するのは、評価が可能な限り遅延されるということです。
&lt;code&gt;@a := map BLOCK, @b&lt;/code&gt;のようなコードを書いたとき、ブロックは一切実行されません。
&lt;code&gt;@a&lt;/code&gt;の要素にアクセスしようとしたときだけ&lt;code&gt;map&lt;/code&gt;は実際にブロックを実行し、必要とされる分だけ&lt;code&gt;@a&lt;/code&gt;を埋めます。&lt;/p&gt;

&lt;p&gt;代入ではなくバインディングを使っていることに注意して下さい: 配列への代入は先行評価を強制することがあります(コンパイラがリストの無限性に気づかない限り; 無限リスト検出の詳細はまだ固まっていません)。
バインディングはそのようなことがありません。&lt;/p&gt;

&lt;p&gt;遅延性は無限リストの取り扱いを可能にします: 引数すべてに操作を行うようなことさえしなければ、評価された要素に必要なだけのメモリしか必要としません。&lt;/p&gt;

&lt;p&gt;しかし落とし穴があります: 長さの取得やソートは遅延性を殺します——無限リストであっても。その場合無限ループになるでしょう。&lt;/p&gt;

&lt;p&gt;一般にスカラへの変換(例えば&lt;code&gt;List.join&lt;/code&gt;)は先行評価です。つまり遅延評価されません。&lt;/p&gt;

&lt;p&gt;遅延性は不必要な計算を防ぎ、それによってコードの簡潔性を保ったままパフォーマンスを上げることができます。&lt;/p&gt;

&lt;p&gt;Perl5で一行ずつファイルを読む場合、&lt;code&gt;for (&amp;lt;HANDLE&amp;gt;)&lt;/code&gt;はファイル全体をメモリに読み込んだ後に走査を始めるのであまり使われませんでした。
遅延性があればこれは問題になりません:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $file = open '/etc/passwd';
for $file.lines -&amp;gt; $line {
    say $line;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;$file.line&lt;/code&gt;はイテレータか遅延リスト(どっちでも同じことです)なので、行は必要な分だけがディスクから物理的に読み込まれます(当然バッファリングはかませた上で)。&lt;/p&gt;

&lt;h3&gt;gather/take&lt;/h3&gt;

&lt;p&gt;遅延リストを作るのに非常に便利な構造が&lt;code&gt;gather { take }&lt;/code&gt;です。
以下のようにして使います:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @list := gather {
    while True {
        # 何か計算;
        take $result;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;gather BLOCK&lt;/code&gt;は遅延リストを返します。
&lt;code&gt;@list&lt;/code&gt;の要素が必要になると&lt;code&gt;take&lt;/code&gt;が実行される位置まで&lt;code&gt;BLOCK&lt;/code&gt;が走ります。
&lt;code&gt;take&lt;/code&gt;は丁度&lt;code&gt;return&lt;/code&gt;のようなもので、&lt;code&gt;take&lt;/code&gt;された要素はすべて&lt;code&gt;@list&lt;/code&gt;の生成に使われます。
&lt;code&gt;@list&lt;/code&gt;の要素がもっと必要になると、ブロックの実行が&lt;code&gt;take&lt;/code&gt;の直後から再開されます。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gather/take&lt;/code&gt;は動的スコープを持つので、&lt;code&gt;gather&lt;/code&gt;の字句的スコープの外で&lt;code&gt;take&lt;/code&gt;を呼ぶことができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @list = gather {
    for 1..10 {
        do_some_computation($_);
    }
}

sub do_some_computation($x) {
    take $x * ($x + 1);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;遅延性の制御&lt;/h3&gt;

&lt;p&gt;遅延性には固有の問題があり(Haskellを学んだことがあるなら、そのIOシステムが遅延性と無副作用性のためにどれだけ妙なことになっているか気づいたでしょう)、時には遅延して欲しくないものもあります。その場合&lt;code&gt;eager&lt;/code&gt;を先頭に付けるだけです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @list = eager map { $block_with_side_effects }, @list;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;逆に言うと、リストだけがデフォルトで遅延されます。ただしスカラも遅延させることができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $ls = lazy { $expansive_computation };
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;計算機科学ではほとんどの問題は可能な組み合わせの木として記述され、その中で解が探索されます。
効率的なアルゴリズムの鍵は効率的な探索法だけではなく、木の重要な部分だけを生成することでもあります。&lt;/p&gt;

&lt;p&gt;遅延リストを使えば、この木と探索法を再帰的に定義し、実際に使っている部分木のみを自動的に生成できます。&lt;/p&gt;

&lt;p&gt;一般に遅延性はプログラミングを簡単にします。計算結果がすべて使われるか気にせず済むからです——遅延評価にするだけで、もし結果が使われなければ計算は実行されず、使われたなら何も損していません。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S02.html#Lists"&gt;http://perlcabal.org/syn/S02.html#Lists&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-1262710309421605661?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/1262710309421605661/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_23.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1262710309421605661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1262710309421605661'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_23.html' title='Perl 5 to 6 - 遅延性'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5499993216415781981</id><published>2011-02-22T19:40:00.003+09:00</published><updated>2011-02-26T00:22:51.379+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - Perl5の演算子に対する変更</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/11-basic-operators.html"&gt;"Perl 5 to 6" Lesson 11 - Changes to Perl 5 Operators&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 11 - Perl5の演算子に対する変更&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;# ビット演算子
5   +| 3;       # 7
6   +^ 3        # 6
5   +&amp;amp; 3;       # 1
"b" ~| "d"      # 'f'

# 文字列連結
'a' ~ 'b'       # 'ab'

# ファイルテスト
if '/etc/passwd' ~~ :e { say "exists" }

# 繰り返し
'a' x 3         # 'aaa'
'a' xx 3        # 'a', 'a', 'a'

# 3項演算子
$a == $b ?? 2 * $a !! $b - $a

# 連結比較
if 0 &amp;lt;= $angle &amp;lt; 2 * pi { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;数値演算子(&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;**&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt;)はすべて元のままです。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;|&lt;/code&gt;、&lt;code&gt;^&lt;/code&gt;、&lt;code&gt;&amp;amp;&lt;/code&gt;はジャンクションの生成に使われるので、ビット演算子は構文が変更されました。
それらはデータプレフィクスを伴い、例えば&lt;code&gt;+|&lt;/code&gt;は数値コンテキストでのOR、&lt;code&gt;~^&lt;/code&gt;は文字列に対する1の補数です。
ビットシフト演算子も同様に変更されました。&lt;/p&gt;

&lt;p&gt;文字列連結は&lt;code&gt;~&lt;/code&gt;になり、&lt;code&gt;.&lt;/code&gt;はメソッド呼び出しに使われます。&lt;/p&gt;

&lt;p&gt;ファイルテストはペア記法で書かれるようになりました。Perl5の&lt;code&gt;-e&lt;/code&gt;は&lt;code&gt;:e&lt;/code&gt;になります。
&lt;code&gt;$_&lt;/code&gt;以外がファイル名として使われる場合、&lt;code&gt;$filename.IO ~~ :e&lt;/code&gt;のようにして与えることができます。&lt;/p&gt;

&lt;p&gt;繰り返し演算子&lt;code&gt;x&lt;/code&gt;は2種類に分けられました: &lt;code&gt;x&lt;/code&gt;は文字列、&lt;code&gt;xx&lt;/code&gt;はリストを繰り返します。&lt;/p&gt;

&lt;p&gt;これまで&lt;code&gt;$condition ? $true : $false&lt;/code&gt;だった3項演算子は&lt;code&gt;$condition ?? $true !! $false&lt;/code&gt;と書かれます。&lt;/p&gt;

&lt;p&gt;比較演算子は連結できるようになりました。&lt;code&gt;$a &amp;lt; $b &amp;lt; $c&lt;/code&gt;のように書けば期待した結果が得られます。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;演算子に対する多くの変更はより良いハフマン符号化を意図しています。つまりよく使われるものには短い名前(メソッド呼び出しの&lt;code&gt;.&lt;/code&gt;のような)、そして滅多に使われない演算子には長い名前(文字列に対するビット単位のANDである&lt;code&gt;~&amp;amp;&lt;/code&gt;のような)ということです。&lt;/p&gt;

&lt;p&gt;連結比較演算子は数学における一般的な記法であり、より自然な言語への前進です。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S03.html#Changes_to_Perl_5_operators"&gt;http://perlcabal.org/syn/S03.html#Changes_to_Perl_5_operators&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5499993216415781981?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5499993216415781981/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6-perl5.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5499993216415781981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5499993216415781981'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6-perl5.html' title='Perl 5 to 6 - Perl5の演算子に対する変更'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5144191478453315710</id><published>2011-02-22T16:41:00.002+09:00</published><updated>2011-02-22T16:43:15.496+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - コンテナと値</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/10-containers-and-values.html"&gt;"Perl 5 to 6" Lesson 10 - Containers and Values&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 10 - コンテナと値&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;my ($x, $y);
$x := $y;
$y = 4;
say $x;             # 4
if $x =:= $y {
    say '$x and $y are different names for the same thing'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Perl6はコンテナと、コンテナに格納できる値を区別して取り扱います。&lt;/p&gt;

&lt;p&gt;通常のスカラ変数は一種のコンテナで、型制約やアクセス制約(読み取り専用とか)などの属性を持ち、他のコンテナの別名として使えます。&lt;/p&gt;

&lt;p&gt;値をコンテナに格納することを代入と呼び、コンテナに別名をつけることをバインディングと呼びます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @a = 1, 2, 3;
my Int $x = 4;
@a[0] := $x;     # @a[0]と$xは同じ変数
@a[0] = 'Foo';   # エラー 「型チェック失敗」
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Int&lt;/code&gt;や&lt;code&gt;Str&lt;/code&gt;のような型は不変、つまりこれらの型のオブジェクトは変更できません。しかしこれらの値を保持する変数(コンテナ)は変更できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $a = 1;
$a = 2;     # 驚くにはあたりません
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;バインディングは&lt;code&gt;::=&lt;/code&gt;演算子を使ってコンパイル時に行うこともできます。&lt;/p&gt;

&lt;p&gt;2つの変数がバインディングされているか調べるには&lt;code&gt;=:=&lt;/code&gt;比較演算子を使います。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;サブルーチンや型、変数のエクスポートやインポートは別名定義によって実現されます。
ややこしい点のある型グロブによる別名定義マジックに代わって、Perl6はシンプルな演算子を提供します。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S03.html#Item_assignment_precedence"&gt;http://perlcabal.org/syn/S03.html#Item_assignment_precedence&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5144191478453315710?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5144191478453315710/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_22.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5144191478453315710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5144191478453315710'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_22.html' title='Perl 5 to 6 - コンテナと値'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-6527048557505957867</id><published>2011-02-19T22:29:00.001+09:00</published><updated>2011-02-19T22:29:38.423+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 比較とマッチング</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/09-comparing-and-matching.html"&gt;"Perl 5 to 6" Lesson 09 - Comparing and Matching&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 09 - 比較とマッチング&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;"ab"    eq      "ab"    True
"1.0"   eq      "1"     False
"a"     ==      "b"     True
"1"     ==      1.0     True
1       ===     1       True
[1, 2]  ===     [1, 2]  False
$x = [1, 2];
$x      ===     $x      True
$x      eqv     $x      True
[1, 2]  eqv     [1, 2]  True
1.0     eqv     1       False

'abc'   ~~      m/a/    True
'abc'   ~~      Str     True
'abc'   ~~      Int     False
Str     ~~      Any     True
Str     ~~      Num     False
1       ~~      0..4    True
-3      ~~      0..4    False
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Perl6もオペランドをスカラコンテキストで評価する文字列比較演算子(&lt;code&gt;eq&lt;/code&gt;, &lt;code&gt;lt&lt;/code&gt;, &lt;code&gt;gt&lt;/code&gt;, &lt;code&gt;le&lt;/code&gt;, &lt;code&gt;ge&lt;/code&gt;, &lt;code&gt;ne&lt;/code&gt;; &lt;code&gt;cmp&lt;/code&gt;は&lt;code&gt;leg&lt;/code&gt;になりました)を持っています。
同様にPerl5にあった数値比較演算子もまだ残っています。&lt;/p&gt;

&lt;p&gt;オブジェクトは単なる&lt;code&gt;bless&lt;/code&gt;されたリファレンスではなくなったので、オブジェクト同士を比較する新しい方法が必要です。
&lt;code&gt;===&lt;/code&gt;は全く同一の値に対してのみ真を返します。数値や文字列などの不変型に対しては通常の等価性テストを行い、他のオブジェクトに対しては両辺が同じオブジェクトを参照している場合のみ(C++のアドレス比較のように)真を返します。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;eqv&lt;/code&gt;は両辺の等価性、つまり同じ型と値を持っているかどうかをテストします。
同じ手順で構築されたデータ構造は等価になります。&lt;/p&gt;

&lt;h3&gt;Smart matching&lt;/h3&gt;

&lt;p&gt;Perl6には「スマートマッチ」演算子と呼ばれる「何でも比較」演算子があり、&lt;code&gt;~~&lt;/code&gt;と書きます。&lt;/p&gt;

&lt;p&gt;この演算子は不変型に対しては単に等値性の比較を行います。
型とのスマートマッチは型適合性をチェックします。
正規表現とのスマートマッチは正規表現とのマッチングを行います。
スカラと&lt;code&gt;Range&lt;/code&gt;オブジェクトのマッチングはスカラが範囲内にあるかどうか調べます。&lt;/p&gt;

&lt;p&gt;他にももっと高度なマッチングがあります: 例えば引数リスト(&lt;code&gt;Capture&lt;/code&gt;)がサブルーチンのパラメータリスト(&lt;code&gt;Signature&lt;/code&gt;)と合うかどうか調べたり、(Perl5でいう&lt;code&gt;-e&lt;/code&gt;のような)ファイルテスト演算子を適用することができます。&lt;/p&gt;

&lt;p&gt;「&lt;code&gt;$x&lt;/code&gt;は&lt;code&gt;$y&lt;/code&gt;に合うかな？」という疑問はどんなものであれ、Perl6ではスマートマッチとして表現されることを覚えておいて下さい。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S03.html#Nonchaining_binary_precedence"&gt;http://perlcabal.org/syn/S03.html#Nonchaining_binary_precedence&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-6527048557505957867?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/6527048557505957867/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_19.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6527048557505957867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6527048557505957867'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_19.html' title='Perl 5 to 6 - 比較とマッチング'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-6396036468255258709</id><published>2011-02-18T23:54:00.002+09:00</published><updated>2011-02-19T00:01:13.961+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - ジャンクション</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/08-junctions.html"&gt;"Perl 5 to 6" Lesson 08 - Junctions&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 08 - ジャンクション&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;if $x eq 3|4 {
    say '$x is either 3 or 4'
}
say ((2|3|4)+7).perl        # (9|10|11)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;ジャンクションは順序づけられていない値の重ね合わせです。ジャンクションに対する演算はジャンクションの各要素に対して別々に実行(並列化されるかも知れません)され、その結果は同じ型のジャンクションに組み立てられます。&lt;/p&gt;

&lt;p&gt;複数あるジャンクション型は真理値コンテキストで評価されたときのみ違いが出ます。型には&lt;code&gt;any&lt;/code&gt;、&lt;code&gt;all&lt;/code&gt;、&lt;code&gt;one&lt;/code&gt;、&lt;code&gt;none&lt;/code&gt;があります。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;型      中置演算子
any     |
one     ^
all     &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;1 | 2 | 3&lt;/code&gt;は&lt;code&gt;any(1..3)&lt;/code&gt;と同じです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my Junction $weekday = any &amp;lt;Monday Tuesday Wednesday 
                            Thursday Friday Saturday Sunday&amp;gt;
if $day eq $weekday {
    say "See you on $day";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;この例では&lt;code&gt;$day&lt;/code&gt;と&lt;code&gt;'Monday'&lt;/code&gt;、&lt;code&gt;$day&lt;/code&gt;と&lt;code&gt;'Tuesday'&lt;/code&gt;などといった各ペアに対して&lt;code&gt;eq&lt;/code&gt;演算子が呼び出され、その結果は再び&lt;code&gt;any&lt;/code&gt;ジャンクションに格納されます。結果が確定するなりすぐに(この場合どれか1つでも比較が真になったら)残りの比較は中止できます。&lt;/p&gt;

&lt;p&gt;ジャンクションは演算子だけでなく、サブルーチンに対しても機能します:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if 2 == sqrt(4 | 9 | 16) {
    say "YaY";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これを可能にするため、ジャンクションは通常の型階層より(ほんのちょっと)外側に位置しています:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;                  Mu
                /    \
               /      \
             Any     Junction
           /  |  \
        All other types
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;もし引数に取ったジャンクションを捕まえて処理するサブルーチンを書きたいなら、パラメータの方を&lt;code&gt;Mu&lt;/code&gt;か&lt;code&gt;Junction&lt;/code&gt;として宣言する必要があります。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub dump_yaml(Junction $stuff) {
    # YAMLがジャンクションを表現できたら良いなあ ;-)
    ....
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;注意: ジャンクションは時々直感に反するふるまいをします。非ジャンクション型では&lt;code&gt;$a != $b&lt;/code&gt;と&lt;code&gt;!($a == $b)&lt;/code&gt;は常に等しいですが、もし一方の変数がジャンクションだとすると違った結果になることがあります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my Junction $b = 3 | 2;
my $a = 2; 
say "Yes" if   $a != $b ;       # Yes
say "Yes" if !($a == $b);       # 出力なし
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;2 != 3&lt;/code&gt;は真なので&lt;code&gt;$a != 2|3&lt;/code&gt;も真です。一方&lt;code&gt;$a == $b&lt;/code&gt;という比較は単一の真理値(True)を返し、その否定はFalseです。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;Perlは自然言語にかなり近くなるよう設計されており、自然言語ではしばしば「もし結果が&lt;code&gt;$this&lt;/code&gt;であるか結果が&lt;code&gt;$that&lt;/code&gt;であるなら」という代わりに「もし結果が&lt;code&gt;$this&lt;/code&gt;か&lt;code&gt;$that&lt;/code&gt;であるなら」のようにいいます。ほとんどのプログラミング言語では前者(を翻訳したもの)だけが許されており、少しぶきっちょな感じがします。
ジャンクションのおかげでPerl6は後者も上手に許可しています。&lt;/p&gt;

&lt;p&gt;それ無しにはループが必要になるような大量の比較が非常に簡単に書けるようにもしています。&lt;/p&gt;

&lt;p&gt;例として数の配列を思い浮かべ、そのすべての要素が非負であることを知りたいと想像して下さい。
Perl5ではこのようなものを書くことになるでしょう:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Perl 5コード:
my @items = get_data();
my $all_non_neg = 1;
for (@items){
    if ($_ &amp;lt; 0) {
        $all_non_neg = 0;
        last;
    }
}
if ($all_non_neg) { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;あるいはたまたま&lt;code&gt;List::MoreUtils&lt;/code&gt;を知っているなら&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use List::MoreUtils qw(all);
my @items = get_data;
if (all { $_ &amp;gt;= 0 } @items) { ...  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perl6では短く、かわいらしいものです:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @items = get_data();
if all(@items) &amp;gt;= 0 { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S03.html#Junctive_operators"&gt;http://perlcabal.org/syn/S03.html#Junctive_operators&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-6396036468255258709?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/6396036468255258709/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_2049.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6396036468255258709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6396036468255258709'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_2049.html' title='Perl 5 to 6 - ジャンクション'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-8013945377915791028</id><published>2011-02-18T01:08:00.007+09:00</published><updated>2011-03-06T00:28:01.115+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 正規表現(またの名をルール)</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/07-rules.html"&gt;"Perl 5 to 6" Lesson 07 - Regexes (also called "rules")&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 07 - 正規表現(またの名をルール)&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;grammar URL {
    token TOP {
        &amp;lt;schema&amp;gt; '://' 
        [&amp;lt;ip&amp;gt; | &amp;lt;hostname&amp;gt; ]
        [ ':' &amp;lt;port&amp;gt;]?
        '/' &amp;lt;path&amp;gt;?
    }
    token byte {
        (\d**{1..3}) &amp;lt;?{ $0 &amp;lt; 256 }&amp;gt;
    }
    token ip {
        &amp;lt;byte&amp;gt; [\. &amp;lt;byte&amp;gt; ] ** 3
    }
    token schema {
        \w+
    }
    token hostname {
        (\w+) ( \. \w+ )*
    }
    token port {
        \d+
    }
    token path {
        &amp;lt;[ a..z A..Z 0..9 \-_.!~*'():@&amp;amp;=+$,/ ]&amp;gt;+
    }
}

my $match = URL.parse('http://perl6.org/documentation/');
say $match&amp;lt;hostname&amp;gt;;       # perl6.org
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;正規表現(Regex)はPerl6で一番改良のあった領域です。Perl5でそうであったほどに正規ではないので、もはや&lt;em&gt;Regular expression&lt;/em&gt;とは呼ばれません。&lt;/p&gt;

&lt;p&gt;訳注: タイトルにある通り「ルール」とも呼ばれるようになりました。この記事でもルールと書いてある部分があります。&lt;/p&gt;

&lt;p&gt;大きく3つの変更点と改良点があります。&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;整理された構文&lt;/dt&gt;
&lt;dd&gt;書き易さを向上させる多くの細かい変更がなされました。例えば&lt;code&gt;.&lt;/code&gt;はすべての文字にマッチするようになり、今までの意味論(改行以外全部)は&lt;code&gt;\N&lt;/code&gt;で提供されるようになりました。

修飾子は正規表現の頭に付くようになり、キャプチャしないグループは&lt;code&gt;(?:...)&lt;/code&gt;より書き易い&lt;code&gt;[...]&lt;/code&gt;になりました。&lt;/dd&gt;

&lt;dt&gt;入れ子のキャプチャとマッチオブジェクト&lt;/dt&gt;
&lt;dd&gt;Perl5では&lt;code&gt;(a(b))(c)&lt;/code&gt;のような正規表現はマッチ成功時には&lt;code&gt;ab&lt;/code&gt;を&lt;code&gt;$1&lt;/code&gt;、&lt;code&gt;b&lt;/code&gt;を&lt;code&gt;$2&lt;/code&gt;、&lt;code&gt;c&lt;/code&gt;を&lt;code&gt;$3&lt;/code&gt;にセットしていました。これは変更され、&lt;code&gt;$0&lt;/code&gt;(列挙は0から始まります)は&lt;code&gt;ab&lt;/code&gt;、&lt;code&gt;$0[0]&lt;/code&gt;と&lt;code&gt;$/[0][0]&lt;/code&gt;が&lt;code&gt;b&lt;/code&gt;、&lt;code&gt;$1&lt;/code&gt;が&lt;code&gt;c&lt;/code&gt;を保持するようになりました。

マッチ変数はすべて&lt;code&gt;$/&lt;/code&gt;経由でもアクセスできます。これは&lt;em&gt;マッチオブジェクト&lt;/em&gt;とも呼ばれ、完全なマッチの木を格納しています。&lt;/dd&gt;

&lt;dt&gt;名前付き正規表現とグラマー&lt;/dt&gt;
&lt;dd&gt;サブルーチンやメソッドのように、正規表現に名前を付けて宣言できます。ルール中で他のルールを&lt;code&gt;&amp;lt;name&amp;gt;&lt;code&gt;のように参照できます。
複数の正規表現をグラマーの中に置くことができます。グラマーはクラスのように継承や合成をサポートしています。&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;これらの変更がルールをPerl5より書き易く、メンテナンスし易いものにしています。&lt;/p&gt;

&lt;p&gt;変更点は極めて多岐に渡るので、ここではその上っ面を擦る程度しか紹介できません。&lt;/p&gt;

&lt;h3&gt;整理された構文&lt;/h3&gt;

&lt;p&gt;レター文字(アンダースコア、数字とすべてのUnicode letter)はそれ自身にマッチし、バックスラッシュでエスケープされた時は特別の(メタ構文的)意味を持ちます。
それ以外の文字の場合は逆になります——これらはエスケープされないときにメタ構文的な役割を持ちます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;字句通り         メタ構文的
a  b  1  2      \a \b \1 \2
\* \: \. \?     *  :  .  ? 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;メタ構文的トークンすべてに意味があるわけではありません(今のところは)。未定義の意味を使うのは不正です。&lt;/p&gt;

&lt;p&gt;文字列を正規表現中でエスケープする方法がもう1つあります: クォートすることです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;m/'a literal text: $#@!!'/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;.&lt;/code&gt;の意味論が変更されたことと、&lt;code&gt;[...]&lt;/code&gt;がキャプチャしないグループになったことは既に述べました。
文字クラスは&lt;code&gt;&amp;lt;[...]&amp;gt;&lt;/code&gt;、否定形の文字クラスは&lt;code&gt;&amp;lt;-[...]&amp;gt;&lt;/code&gt;です。&lt;code&gt;^&lt;/code&gt;と&lt;code&gt;$&lt;/code&gt;はいつでも文字列の先頭と末尾にマッチします。行の先頭や末尾にマッチさせるには&lt;code&gt;^^&lt;/code&gt;と&lt;code&gt;$$&lt;/code&gt;を使って下さい。&lt;/p&gt;

&lt;p&gt;これは修飾子&lt;code&gt;/s&lt;/code&gt;と&lt;code&gt;/m&lt;/code&gt;がなくなったということです。修飾子は正規表現の頭に付くようになり、ペアとして書かれます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if "abc" ~~ m:i/B/ {
    say "Match";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;修飾子は短い形式と長い形式があります。昔の&lt;code&gt;/x&lt;/code&gt;修飾子はデフォルトになりました。つまり、空白は無視されます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;短い形式 長い形式         意味
--------------------------------------------------------------
:i      :ignorecase     大文字小文字の違いを無視する(かつての/i)
:m      :ignoremark     記号を無視する(アクセント記号、分音記号など)
:g      :global         可能な限り繰り返しマッチする(/g)
:s      :sigspace       正規表現中の空白が(省略可能な)空白にマッチする
:P5     :Perl5          Perl5互換の構文に戻す
:4x     :x(4)           4回マッチする(他の数字でも同様)
:3rd    :nth(3)         3番目のマッチ
:ov     :overlap        :gと似ているが、範囲がオーバーラップしたマッチも考慮する
:ex     :exhaustive     マッチ可能性をすべて尽くす
        :ratchet        バックトラックしない
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;:sigspace&lt;/code&gt;にはもう少し説明が必要です。これはパターン中のすべての空白を&lt;code&gt;&amp;lt;.ws&amp;gt;&lt;/code&gt;(ルール&lt;code&gt;ws&lt;/code&gt;を呼び出し、結果を保存しません)に置換します。このルールはオーバーライドできます。デフォルトではワード文字列で囲まれている場合は1個以上の空白にマッチし、それ以外の位置では0個以上の空白にマッチします。&lt;/p&gt;

&lt;p&gt;(他にも新しい修飾子はありますが、ここに挙げたものよりは重要ではないでしょう)&lt;/p&gt;

&lt;h3&gt;マッチオブジェクト&lt;/h3&gt;

&lt;p&gt;すべてのマッチはマッチオブジェクトと呼ばれるものを生成し、特殊変数&lt;code&gt;$/&lt;/code&gt;に格納します。
これにはいろいろな使い方ができます。真理値コンテキストではマッチ成功時には&lt;code&gt;Bool::True&lt;/code&gt;を返します。文字列コンテキストではマッチした文字列を返し、リストとして使われればキャプチャのリストを返します。ハッシュとして使われると名前付きキャプチャを返します。
&lt;code&gt;.from&lt;/code&gt;メソッドと&lt;code&gt;.to&lt;/code&gt;メソッドはマッチした先頭と末尾の位置を返します。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if 'abcdefg' ~~ m/(.(.)) (e | bla ) $&amp;lt;foo&amp;gt; = (.) / {
    say $/[0][0];           # d
    say $/[0];              # cd
    say $/[1];              # e
    say $/&amp;lt;foo&amp;gt;             # f
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;$0&lt;/code&gt;や&lt;code&gt;$1&lt;/code&gt;などは&lt;code&gt;$/[0]&lt;/code&gt;や&lt;code&gt;$/[1]&lt;/code&gt;などの単なる別名です。同様に&lt;code&gt;$/&amp;lt;x&amp;gt;&lt;/code&gt;と&lt;code&gt;$/{'x'}&lt;/code&gt;は&lt;code&gt;$&amp;lt;x&amp;gt;&lt;/code&gt;という別名を持ちます。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$/[...]&lt;/code&gt;や&lt;code&gt;$/{...}&lt;/code&gt;でアクセスできるものもまた、マッチオブジェクト(あるいはそのリスト)であることに留意して下さい。
これによってルールの完全な解析木を作ることができます。&lt;/p&gt;

&lt;h3&gt;名前付き正規表現とグラマー&lt;/h3&gt;

&lt;p&gt;ルールは旧来の&lt;code&gt;m/.../&lt;/code&gt;で使ったり、サブルーチンやメソッドのように宣言することができます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;regex a { ... }
token b { ... }
rule  c { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これらの違いは、&lt;code&gt;token&lt;/code&gt;は&lt;code&gt;:ratchet&lt;/code&gt;修飾子が有効になり(バックトラックしなくなる。Perl5で正規表現の各部を&lt;code&gt;(?&amp;gt;...)&lt;/code&gt;で囲むようなもの)、&lt;code&gt;rule&lt;/code&gt;は&lt;code&gt;:ratchet&lt;/code&gt;と&lt;code&gt;:sigspace&lt;/code&gt;が有効になることです。
このようなルール(どのキーワードで宣言したかに関係なくルールと呼びます)を呼び出すには、その名前を角カッコで囲みます: &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;。これはサブルールを文字列の現在からマッチさせ、結果を&lt;code&gt;$/&amp;lt;a&amp;gt;&lt;/code&gt;に格納します。つまりこれは名前付きキャプチャです。
結果をキャプチャすることなくルールを呼び出すには、名前の先頭にドットを付けます: &lt;code&gt;&amp;lt;.a&amp;gt;&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;グラマーはルールの寄せ集めで、クラスに似ています(例えばSYNOPSISを見て下さい)。グラマーは継承したり、ルールをオーバーライドしたりできます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grammar URL::HTTP is URL {
    token schema { 'http' }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;Perl5の正規表現は解読不能になることがよくありますが、グラマーは巨大な正規表現を小さな読み易い断片に分割することを促進します。
名前付きキャプチャはルールを自己文書化し、多くのものが以前より一貫性ある形になりました。&lt;/p&gt;

&lt;p&gt;最後に、グラマーはPerl6を含むほとんどすべてのプログラミング言語を構文解析できるくらい強力です。
このことがPerl6の構文をPerl5よりメンテナンスし易く、変更し易いものにしています(訳注: &lt;a href="http://perl6.org/compilers/std-viv"&gt;Perl6の構文はグラマーを使って定義されている&lt;/a&gt;)。Perl5では構文解析器はCで書かれており、構文解析時に変更できませんでした。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S05.html"&gt;http://perlcabal.org/syn/S05.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-8013945377915791028?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/8013945377915791028/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_18.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8013945377915791028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8013945377915791028'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_18.html' title='Perl 5 to 6 - 正規表現(またの名をルール)'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5553042557549900247</id><published>2011-02-16T23:52:00.006+09:00</published><updated>2011-03-06T00:26:30.325+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - コンテキスト</title><content type='html'>&lt;p&gt;&lt;em&gt;2011-02-27: &lt;a href="#comments"&gt;コメント欄で既に改訂された仕様の指摘がありました&lt;/a&gt;ので一部補足しました。&lt;a href="http://d.hatena.ne.jp/uasi/"&gt;id:uasi&lt;/a&gt;に感謝します。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/06-contexts.html"&gt;"Perl 5 to 6" Lesson 06 - Contexts&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 06 - コンテキスト&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;my @a = &amp;lt;a b c&amp;gt;
my $x = @a;
say $x[2];          # c
say (~2).WHAT       # Str()
say +@a;            # 3
if @a &amp;lt; 10 { say "short array"; }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;次のように書いたとき、&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$x = @a
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perl5では&lt;code&gt;$x&lt;/code&gt;は&lt;code&gt;@a&lt;/code&gt;より少ない情報——&lt;code&gt;@a&lt;/code&gt;の要素数だけ——しか持ちません。
すべての情報を保存しておくためには明示的にリファレンスを取る必要があります: &lt;code&gt;$x = \@a&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Perl6ではこれらは反対になります: デフォルトでは何も失うことなく、スカラ変数は配列を単に格納します。
これは一般要素コンテキスト(Perl5で&lt;em&gt;scalar&lt;/em&gt;と呼ばれていたもの)及びより特化された数値、整数、文字列コンテキストの導入によって可能となりました。無効コンテキストとリストコンテキストは変更されていません。&lt;/p&gt;

&lt;p&gt;特別な構文でコンテキストを強制できます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;構文         コンテキスト

~stuff       文字列
?stuff       真理値
+stuff       数値
-stuff       数値 (符号を変える効果もある)
$( stuff )   一般要素コンテキスト
@( stuff )   リストコンテキスト
%( stuff )   ハッシュコンテキスト
@@( stuff )  lolコンテキスト
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;lolコンテキスト&lt;/h3&gt;

&lt;p&gt;新しいコンテキストに&lt;del&gt;スライスコンテキスト&lt;/del&gt;&lt;ins&gt;lol(List of List)コンテキスト&lt;/ins&gt;(&lt;a href="#comments"&gt;コメントで指摘があった&lt;/a&gt;ので修正しました。多謝)というものもあります。これは内包するリストを展開しないリストコンテキストです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; @( &amp;lt;a b&amp;gt; Z &amp;lt;c d&amp;gt; )     # &amp;lt;a c b d&amp;gt;
@@( &amp;lt;a b&amp;gt; Z &amp;lt;c d&amp;gt; )     # (['a', 'c'], ['b', 'd'])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これが導入されたのは、多くの組み込み関数が2つのバージョン——フラットなリストを返すバージョンと、リストのリストを返すバージョン——を持っていることが分かったからです。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@@( stuff )&lt;/code&gt;でlolコンテキストを強制できます。&lt;/p&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;より特化されたコンテキストは設計上の選択を遅らせる手段になります——例えばスカラコンテキストでリストが何を返すか決めてしまうのは気が早すぎます。リストへのリファレンスはすべての情報を保存していますが、数値比較式の中では役に立ちません。このようにどんな選択も全員を満足させることはできません。&lt;/p&gt;

&lt;p&gt;特化コンテキストのおかげでこのような選択をする必要はありません——コンテキストはよく考慮されたデフォルト値を返し、それを望まない演算子は単により特化したコンテキストを伝播させることができます。&lt;/p&gt;

&lt;p&gt;それら異なったコンテキストは、マッチオブジェクトのようなオブジェクトの有用性やコードの美しさをより高めます。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S02.html#Context"&gt;http://perlcabal.org/syn/S02.html#Context&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://perlgeek.de/blog-en/perl-6/immutable-sigils-and-context.html"&gt;http://perlgeek.de/blog-en/perl-6/immutable-sigils-and-context.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5553042557549900247?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5553042557549900247/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_16.html#comment-form' title='2 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5553042557549900247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5553042557549900247'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_16.html' title='Perl 5 to 6 - コンテキスト'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3320369698507379766</id><published>2011-02-15T23:32:00.001+09:00</published><updated>2011-02-15T23:45:24.987+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - オブジェクトとクラス</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/05-objects-and-classes.html"&gt;"Perl 5 to 6" Lesson 05 - Objects and Classes&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 05 - オブジェクトとクラス&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;class Shape {
    method area { ... }    # リテラル '...'
    has $.colour is rw;
}

class Rectangle is Shape {
    has $.width;
    has $.height;

    method area {
        $!width * $!height;
    }
}

my $x = Rectangle.new(
        width   =&amp;gt; 30.0,
        height  =&amp;gt; 20.0,
        colour  =&amp;gt; 'black',
    );
say $x.area;                # 600
say $x.colour;              # black
$x.colour = 'blue';
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Perl6にはPerl5よりずっと洗練されたオブジェクトモデルがあります。クラス、ロール、アトリビュートやメソッドのためのキーワードがあり、カプセル化されたプライベートなアトリビュートやメソッドがあります。
これは(Perl6のオブジェクトシステムに影響を受けた)Perl5の&lt;a href="http://www.iinteractive.com/moose/"&gt;Moose&lt;/a&gt;モジュールにとてもよく似ています。&lt;/p&gt;

&lt;p&gt;クラスを宣言する方法は2通りあります。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class ClassName;
# ここにクラス定義を書く
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;1つは&lt;code&gt;class ClassName;&lt;/code&gt;で始まるもので、ファイルの終端までを範囲とします。
もう1つはクラス名にブロックが続くもので、ブロックの中身がクラス定義とみなされます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class YourClass {
    # ここにクラス定義を書く
}
# 他のクラスやコード
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;メソッド&lt;/h3&gt;

&lt;p&gt;メソッドは&lt;code&gt;method&lt;/code&gt;キーワードで宣言されます。メソッド中では&lt;code&gt;self&lt;/code&gt;キーワードを使って呼び出し元オブジェクト(Invocant)を参照できます。&lt;/p&gt;

&lt;p&gt;シグネチャリストの最初のパラメータに&lt;code&gt;:&lt;/code&gt;を付けることで、読み出し元オブジェクトに別名を付けて参照することもできます。&lt;/p&gt;

&lt;p&gt;パブリックなメソッドは引数を取らない場合は&lt;code&gt;$object.method&lt;/code&gt;、引数を取る場合は&lt;code&gt;$object.method(@args)&lt;/code&gt;あるいは&lt;code&gt;$object.method: @args&lt;/code&gt;という構文で呼び出すことができます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class SomeClass {
    # 何もせずに呼び出し元オブジェクトを返す
    method foo {
        return self;
    }
    method bar($s: ) {
        return $s;
    }
}
my SomeClass $x .= new;
$x.foo.bar                      # $xと同じ
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(&lt;code&gt;my SomeClass $x .= new&lt;/code&gt;は&lt;code&gt;my SomeClasss $x .= SomeClass.new&lt;/code&gt;の省略形です。型宣言がSomeClassクラスを表すオブジェクトである「型オブジェクト」を補完してくれます)&lt;/p&gt;

&lt;p&gt;メソッドはサブルーチンと同様に他の引数も取ることができます。&lt;/p&gt;

&lt;p&gt;プライベートメソッドは&lt;code&gt;method !method_name&lt;/code&gt;で宣言され、&lt;code&gt;self!method_name&lt;/code&gt;で呼び出せます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Foo {
    method !private($frob) {
        return "Frobbed $frob";
    }

    method public {
        say self!private("foo");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;プライベートメソッドをクラスの外から呼び出すことはできません。&lt;/p&gt;

&lt;h3&gt;アトリビュート&lt;/h3&gt;

&lt;p&gt;アトリビュートは&lt;code&gt;has&lt;/code&gt;キーワードで宣言され、シジルの後に特別な文字である「ツイジル(Twigil)」が付きます。プライベートアトリビュートには&lt;code&gt;!&lt;/code&gt;、パブリックアトリビュートには&lt;code&gt;.&lt;/code&gt;が付きます。
パブリックアトリビュートは単にパブリックなアクセサを持つプライベートアトリビュートです。
したがってアトリビュートの値を変更したい場合は、&lt;code&gt;!&lt;/code&gt;ツイジルを使ってアクセサを介さずアトリビュート自身にアクセスする必要があります(アクセサが&lt;code&gt;is rw&lt;/code&gt;である場合を除く)。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class SomeClass {
    has $!a;
    has $.b;
    has $.c is rw;

    method set_stuff {
        $!a = 1;    # OK、クラス内からのアトリビュートに対する書き込み
        $!b = 2;    # 同上
        $.b = 3;    # エラー、読み出し専用アクセサには書き込めない
    }

    method do_stuff {
        # パブリックな名前の代わりにプライベートな名前を使えます
        # $!bと$.bは同じものを表します
        return $!a + $!b + $!c;
    }
}
my $x = SomeClass.new;
say $x.a;       # エラー!
say $x.b;       # OK
$x.b = 2;       # エラー!
$x.c = 3;       # OK
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;継承&lt;/h3&gt;

&lt;p&gt;継承は&lt;code&gt;is&lt;/code&gt;トレイトを使って行います。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Foo is Bar { 
    # FooクラスはBarクラスから継承する
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;一般的な継承ルールはすべて適用されます——メソッドはまず実際の型の中で探索され、見つからない場合は親クラスを再帰的に探索します。派生クラスの型は親クラスの型としても振る舞います:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Bar { }
class Foo is Bar { }
my Bar $x = Foo.new();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;この例では&lt;code&gt;$x&lt;/code&gt;の型は&lt;code&gt;Bar&lt;/code&gt;であり、「すべての&lt;code&gt;Foo&lt;/code&gt;は&lt;code&gt;Bar&lt;/code&gt;である」ため&lt;code&gt;Foo&lt;/code&gt;のオブジェクトが代入できます。&lt;/p&gt;

&lt;p&gt;複数のクラスから多重継承できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class ArrayHash is Hash is Array { 
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;ロールと合成&lt;/h3&gt;

&lt;p&gt;世界は階層的にはできていませんから、何もかもを継承階層に押し込めるのが難しいこともあります。
これがPerl6にロールがある理由の1つです。ロールはクラスにとてもよく似ていますが、直接オブジェクトを作ることはできません。
クラスは型適合性の保証がその第一の目的ですが、ロールはコードの再利用を第一義としています。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;role Paintable {
    has $.colour is rw;
    method paint { ... }
}
class Shape {
    method area { ... }
}

class Rectangle is Shape does Paintable {
    has $.width;
    has $.height;
    method area {
        $!width * $!height;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S12.html"&gt;http://perlcabal.org/syn/S12.html&lt;/a&gt;
&lt;a href="http://perlcabal.org/syn/S14.html"&gt;http://perlcabal.org/syn/S14.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3320369698507379766?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3320369698507379766/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_15.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3320369698507379766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3320369698507379766'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6_15.html' title='Perl 5 to 6 - オブジェクトとクラス'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3033402363419414594</id><published>2011-02-15T00:24:00.002+09:00</published><updated>2011-03-06T00:22:47.120+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - サブルーチンとシグネチャ</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/04-subs-and-signatures.html"&gt;"Perl 5 to 6" Lesson 04 - Subroutines and Signatures&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 04 - サブルーチンとシグネチャ&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;# シグネチャなしのサブルーチン——Perl5風
sub print_arguments {
    say "Arguments:";
    for @_ {
        say "\t$_";
    }
}

# 固定引数の型指定付きシグネチャ
sub distance(Int $x1, Int $y1, Int $x2, Int $y2) {
    return sqrt ($x2-$x1)**2 + ($y2-$y1)**2;
}
say distance(3, 5, 0, 1); 

# デフォルト引数
sub logarithm($num, $base = 2.7183) {
    return log($num) / log($base)
}
say logarithm(4);       # 第2引数はデフォルトを利用
say logarithm(4, 2);    # 明示的な第2引数

# 名前付き引数
sub doit(:$when, :$what) {
    say "doing $what at $when";
}
doit(what =&amp;gt; 'stuff', when =&amp;gt; 'once');  # 'doing stuff at once'
doit(:when&amp;lt;noon&amp;gt;, :what('more stuff')); # 'doing more stuff at noon'
# 不正: doit("stuff", "now")
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;サブルーチンは&lt;code&gt;sub&lt;/code&gt;キーワードで宣言され、CやJavaその他の言語と同様に形式的パラメータを持ちます。これらのパラメータは型制約をとることもできます。&lt;/p&gt;

&lt;p&gt;パラメータはデフォルトでは読み出し専用です。この挙動はいわゆる「Trait」で変更できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub foo($bar) {
    $bar = 2;       # 禁止されている
}

my $x = 2;
sub baz($bar is rw) {
    $bar = 0;       # 許される
}
baz($x); say $x;    # 0

sub quox($bar is copy){
    $bar = 3;
}
quox($x); say $x    # まだ0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;パラメータは&lt;code&gt;?&lt;/code&gt;を後ろに付けたり、デフォルト値を与えることでオプションにできます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub foo($x, $y?) {
    if $y.defined {
        say "WE CAN HAZ $y"
    }
}

sub bar($x, $y = 2 * $x) { 
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;名前付きパラメータ&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;my_sub($first, $second)&lt;/code&gt;のようにしてサブルーチンを呼び出すとき、&lt;code&gt;$first&lt;/code&gt;は最初の形式的パラメータに、&lt;code&gt;$second&lt;/code&gt;は2番目の形式的パラメータに、といった具合に結びつきます。このようなパラメータを「位置的」パラメータと呼んでいます。&lt;/p&gt;

&lt;p&gt;数を数えるより名前を思い出す方が簡単なことは往々にしてあるので、Perl6は名前付きパラメータも持っています:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $r = Rectangle.new( 
        x       =&amp;gt; 100, 
        y       =&amp;gt; 200, 
        height =&amp;gt; 23,
        width  =&amp;gt; 42,
        color  =&amp;gt; 'black'
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;引数が具体的に何を意味しているか、見るなりすぐに理解できます。&lt;/p&gt;

&lt;p&gt;名前付きパラメータを定義するには、単にパラメータの前に&lt;code&gt;:&lt;/code&gt;を置くだけです:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub area(:$width, :$height) {
    return $width * $height;
}
area(width =&amp;gt; 2,  height =&amp;gt; 3);
area(height =&amp;gt; 3, width =&amp;gt; 2 ); # 同じ
area(:height(3), :width(2));    # 同じ
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ここまでの例では変数名がパラメータの名前としても使われていますが、別の名前を使うこともできます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub area(:width($w), :height($h)){
    return $w * $h;
}
area(width =&amp;gt; 2,  height =&amp;gt; 3);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;名前付き引数は名前を使ってのみ渡すことができ、位置による指定はできません。一方で位置的引数は名前を使って渡すこともできます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub sqrt($number) { ... };
sqrt(3);
sqrt(number =&amp;gt; 3); # これも動く
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;丸呑み(Slurpy)引数&lt;/h3&gt;

&lt;p&gt;サブルーチンにシグネチャを付けることは、前もって引数の数を知っておかなければならないということではありません。
残された引数を使い切る、丸呑み(slurpy)パラメータを(通常のパラメータの後に)定義することができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub tail ($first, *@rest){
    say "First: $first";
    say "Rest: @rest[]";
}
tail(1, 2, 3, 4);           # "First: 1\nRest: 2 3 4\n"
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;変数展開&lt;/h3&gt;

&lt;p&gt;デフォルトでは配列は引数リストに展開されません。したがってPerl5とは異なり次のようなコードが書けます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub a($scalar1, @list, $scalar2){
    say $scalar2;
}

my @list = "foo", "bar";
a(1, @list, 2);                  # 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これはデフォルトではリストを引数リストとして使えないということでもあります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @indexes = 1, 4;
say "abc".substr(@indexes)       # エラー!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;プレフィクス&lt;code&gt;|&lt;/code&gt;を付けると期待した動作をします:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say "abcdefgh".substr(|@indexes) # bcde
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;多重サブルーチン&lt;/h3&gt;

&lt;p&gt;異なるパラメータリストを持つ同名のサブルーチンを複数定義できます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi sub my_substr($str) { ... }                          # 1
multi sub my_substr($str, $start) { ... }                  # 2
multi sub my_substr($str, $start, $end) { ... }            # 3
multi sub my_substr($str, $start, $end, $subst) { ... }    # 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;このようなサブルーチンを呼び出すと、パラメータリストが一致するものが選ばれます。&lt;/p&gt;

&lt;p&gt;多重サブルーチンは引数の数で区別できる必要はなく、パラメータの型でも区別します:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi sub frob(Str $s) { say "Frobbing String $s"  }
multi sub frob(Int $i) { say "Frobbing Integer $i" }

frob("x")       # Frobbing String x
frob(2)         # Frobbing Integer 2
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;明示的な型シグネチャの有用性を疑う人はいません: タイピング量は削減され、重複引数の確認は省け、より自己文書化されたコードになります。
名前付きパラメータの価値も既に議論され切っています。&lt;/p&gt;

&lt;p&gt;これはまた有用なイントロスペクションを提供します。例えばブロックかサブルーチンを&lt;code&gt;Array.sort&lt;/code&gt;に渡したとして、そのコードが1つだけ引数を取るとすると、&lt;a href="http://en.wikipedia.org/wiki/Schwartzian_transform"&gt;シュワルツ変換&lt;/a&gt;が自動的に行われます——このような機能はPerl5では不可能でした。明示的なシグネチャを欠いているため、&lt;code&gt;sort&lt;/code&gt;はコードブロックが何個の引数を取るのか判断できないからです。&lt;/p&gt;

&lt;p&gt;多重サブルーチンは組み込み関数を新しい型に対してオーバーライドできるという点で非常に便利です。例えばあなたが(大文字と小文字の変換に独特の規則がある)トルコ語の文字列を正しく扱えるようにローカライズされたバージョンのPerl6を欲しがっているとしましょう。&lt;/p&gt;

&lt;p&gt;言語を改変する代わりに単にTurkishStrという新しい型を導入し、組み込み関数に多重サブルーチンを追加するだけです:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi uc(TurkishStr $s) { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これで文字列が言語に対応した型を持っているかだけ気をつければ、&lt;code&gt;uc&lt;/code&gt;を通常の組み込み関数のように使えます。&lt;/p&gt;

&lt;p&gt;演算子もサブルーチンなので、これらの改善点は演算子についても同様に働きます。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S06.html"&gt;http://perlcabal.org/syn/S06.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3033402363419414594?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3033402363419414594/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3033402363419414594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3033402363419414594'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl-5-to-6.html' title='Perl 5 to 6 - サブルーチンとシグネチャ'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3269783768394067471</id><published>2011-02-14T16:38:00.010+09:00</published><updated>2011-03-07T01:22:59.652+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 基本制御構造</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/03-control-structures.html"&gt;"Perl 5 to 6" Lesson 03 - Basic Control Structures&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 03 - 基本制御構造&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;if $percent &amp;gt; 100  {
    say "weird mathematics";
}
for 1..3 {
    # $_をループ変数として使う
    say 2 * $_;
}
for 1..3 -&amp;gt; $x {
    # 明示的なループ変数を使う
    say 2 * $x;
}

while $stuff.is_wrong {
    $stuff.try_to_make_right;
}

die "Access denied" unless $password eq "Secret";
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;ほとんどのPerl5の制御構造はPerl 6でもよく似ています。
一番大きな見た目の変化は&lt;code&gt;if&lt;/code&gt;、&lt;code&gt;while&lt;/code&gt;、&lt;code&gt;for&lt;/code&gt;などの後にカッコが必要なくなったことです。&lt;/p&gt;

&lt;p&gt;正確には、条件をカッコで囲むのは非推奨です。&lt;/p&gt;

&lt;h3&gt;分岐&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;if&lt;/code&gt;はほとんど変わっていません。相変わらず&lt;code&gt;elsif&lt;/code&gt;や&lt;code&gt;else&lt;/code&gt;の節を付けることができます。
&lt;code&gt;unless&lt;/code&gt;もありますが、&lt;code&gt;else&lt;/code&gt;節を付けることができなくなりました。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if $sheep == 0 {
    say "How boring";
} elsif $sheep == 1 {
    say "One lonely sheep";
} else {
    say "A herd, how lovely!";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;if&lt;/code&gt;や&lt;code&gt;unless&lt;/code&gt;を文修飾子として(つまり文の後に付けて)使うこともできます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say "you won" if $answer == 42;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;ループ&lt;/h3&gt;

&lt;p&gt;Perl5と同様、&lt;code&gt;next&lt;/code&gt;と&lt;code&gt;last&lt;/code&gt;でループを制御できます。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;for&lt;/code&gt;ループはリストを走査する場合のみに使われるようになりました。
ループ変数が与えられない場合はデフォルトで&lt;code&gt;$_&lt;/code&gt;が使われます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for 1..10 -&amp;gt; $x {
    say $x;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;-&amp;gt; $x { ... }&lt;/code&gt;という部分は「ポインティ・ブロック」と呼ばれ、無名サブルーチン、あるいはLispのlambdaのようなものです。&lt;/p&gt;

&lt;p&gt;1つ以上のループ変数を使うこともできます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for 0..5 -&amp;gt; $even, $odd {
    say "Even: $even \t Odd: $odd";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これはハッシュを走査する方法でもあります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my %h = a =&amp;gt; 1, b =&amp;gt; 2, c =&amp;gt; 3;
for %h.kv -&amp;gt; $key, $value {
    say "$key: $value";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cスタイルの&lt;code&gt;for&lt;/code&gt;ループは&lt;code&gt;loop&lt;/code&gt;という名前になりました(これはカッコを必要とする唯一のループ構造でもあります):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;loop (my $x = 1; $x &amp;lt; 100; $x = $x**2) {
    say $x;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S04.html#Conditional_statements"&gt;http://perlcabal.org/syn/S04.html#Conditional_statements&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3269783768394067471?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3269783768394067471/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6_14.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3269783768394067471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3269783768394067471'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6_14.html' title='Perl 5 to 6 - 基本制御構造'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5367207681890056396</id><published>2011-02-13T11:32:00.006+09:00</published><updated>2011-02-27T12:35:20.503+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 型</title><content type='html'>&lt;p&gt;&lt;em&gt;2011-02-27: &lt;a href="#comments"&gt;コメント欄で既に改訂された仕様の指摘がありました&lt;/a&gt;ので一部補足しました。&lt;a href="http://d.hatena.ne.jp/uasi/"&gt;id:uasi&lt;/a&gt;に感謝します。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/02-types.html"&gt;"Perl 5 to 6" Lesson 02 - Types&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 02 - 型&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;my Int $x = 3;
$x = "foo";         # エラー
say $x.WHAT;        # 'Int()'

# 型チェック:
if $x ~~ Int {
    say '$x contains an Int'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Perl6には型があります。すべてが何らかの形のオブジェクトであり、型を持ちます。変数は型制約を持つことができますが、必須ではありません。&lt;/p&gt;

&lt;p&gt;知っておくべきいくつかの基本的な型があります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'a string'      # Str
2               # Int
3.14            # Rat (有理数)
(1, 2, 3)       # Seq
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;「通常の」組み込み型はすべて大文字で始まります。「通常の」型はすべて&lt;code&gt;Any&lt;/code&gt;を継承し、他も含めたすべての型は&lt;del&gt;&lt;code&gt;Object&lt;/code&gt;&lt;/del&gt;&lt;ins&gt;&lt;code&gt;Mu&lt;/code&gt;&lt;/ins&gt;(&lt;a href="#comments"&gt;コメントで指摘があった&lt;/a&gt;ので修正しました。多謝。ちなみに「無」から来ているそうです)を継承します。&lt;/p&gt;

&lt;p&gt;型名を変数宣言に加えることで、変数が保持できる値の型に制約をつけられます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my Numeric $x = 3.4;
my Int @a = 1, 2, 3;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;「間違った」型(与えられた型でもその派生型でもない型)の値を変数に代入しようとするとエラーになります。&lt;/p&gt;

&lt;p&gt;配列に対する型宣言はその要素に対して適用されるので、&lt;code&gt;my Str @s&lt;/code&gt;は文字列だけを格納できる配列になります。&lt;/p&gt;

&lt;p&gt;いくつかの型は更に詳細な型の族を表します。例えば整数、有理数と浮動小数(&lt;code&gt;Num&lt;/code&gt;型)は&lt;code&gt;Numeric&lt;/code&gt;型を構成します。&lt;/p&gt;

&lt;h3&gt;イントロスペクション&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;.WHAT&lt;/code&gt;メソッドを呼ぶことでインスタンスの型を知ることができます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say "foo".WHAT;     # Str()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ただし、もしインスタンスが与えられた型を継承しているか確認したいのなら別の方法があります。
継承関係も考慮してくれるのでこちらの方がオススメです:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if $x ~~ Int {
    say 'Variable $x contains an integer';
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;MOTIVATION&lt;/h2&gt;

&lt;p&gt;型システムの詳細をすべて完全に理解することは簡単ではありませんが、型が必要な理由があります:&lt;/p&gt;

&lt;h3&gt;安全なプログラミング&lt;/h3&gt;

&lt;p&gt;インスタンスがある型であると宣言すれば然るべき処理を実行することを確信できます。確認の必要はありません。&lt;/p&gt;

&lt;h3&gt;最適化可能性&lt;/h3&gt;

&lt;p&gt;コンパイル時に型情報があれば然るべき最適化を行うことができます。
Perl6は必ずしもCより遅くなりません。原理的には。&lt;/p&gt;

&lt;h3&gt;拡張性&lt;/h3&gt;

&lt;p&gt;型情報と多重ディスパッチによって、特定の型に対して演算を簡単に再定義できます。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S02.html#Built-In_Data_Types"&gt;http://perlcabal.org/syn/S02.html#Built-In_Data_Types&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5367207681890056396?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5367207681890056396/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6_13.html#comment-form' title='2 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5367207681890056396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5367207681890056396'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6_13.html' title='Perl 5 to 6 - 型'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-2238150778338503343</id><published>2011-02-12T00:51:00.010+09:00</published><updated>2011-03-06T23:38:34.413+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - 文字列、配列、ハッシュ</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/01-strings-arrays-hashes.html"&gt;"Perl 5 to 6" Lesson 01 - Strings, Arrays, Hashes;&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" Lesson 01 - 文字列、配列、ハッシュ&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;my $five = 5;
print "an interpolating string, just like in perl $five\n";
say 'say() adds a newline to the output, just like in perl 5.10';

my @array = 1, 2, 3, 'foo';
my $sum = @array[0] + @array[1];
if $sum &amp;gt; @array[2] {
    say "not executed";
}
my $number_of_elems = @array.elems;     # or +@array
my $last_item = @array[*-1];

my %hash = foo =&amp;gt; 1, bar =&amp;gt; 2, baz =&amp;gt; 3;
say %hash{'bar'};                       # 2
say %hash&amp;lt;bar&amp;gt;;                         # 自動クォートを使った例
# これはエラーになる: %hash{bar}
# (宣言されていないサブルーチンbar()を呼び出そうとする)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Perl6はPerl5と良く似ています――より良いだけです。
文はセミコロンで終端します。ブロックの最後の文と、行の最後の閉じ中カッコの後では省略可能です。&lt;/p&gt;

&lt;p&gt;変数は相変わらず(&lt;code&gt;$&lt;/code&gt;、&lt;code&gt;@&lt;/code&gt;、&lt;code&gt;%&lt;/code&gt;のような)シジル(Sigil)で始まりますし、多くのPerl5組み込み関数はPerl6でも変更されていません。&lt;/p&gt;

&lt;h3&gt;文字列&lt;/h3&gt;

&lt;p&gt;文字列はダブルクォート(変数展開する場合)かシングルクォートで囲みます。バックスラッシュのエスケープはPerl5と同様に作用します。&lt;/p&gt;

&lt;p&gt;ただし変数展開の規則は少し変更されました。以下のものは展開されます。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $scalar = 6;
my @array = 1, 2, 3;
say "Perl $scalar";         # 'Perl 6'
say "An @array[]";          # 'An 1 2 3', 禅スライス(Zen slice)とも呼ばれる
say "@array[1]";            # '2'
say "Code: { $scalar * 2 }" # 'Code: 12'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;配列とハッシュは添字(あるいはカッコが付いた&lt;code&gt;"some $obj.method()"&lt;/code&gt;のような関数呼び出し)が付いた場合のみ展開されます。空の添字はデータ構造全体を展開します。&lt;/p&gt;

&lt;p&gt;中カッコの中のブロックはコードとして実行され、結果が文字列中に展開されます。&lt;/p&gt;

&lt;h3&gt;配列&lt;/h3&gt;

&lt;p&gt;配列変数は相変わらず&lt;code&gt;@&lt;/code&gt;シジルで始まります。
格納された要素にアクセスするとき、例えば添字が1つ与えられた場合であってもそのままです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @a = 5, 1, 2;            # カッコは必要なくなりました
say @a[0];                  # そう、@で始まるんです
say @a[0, 2];               # スライスも使えます
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;リストはカンマ演算子で生成されます。&lt;code&gt;1,&lt;/code&gt;はリストですが、&lt;code&gt;(1)&lt;/code&gt;は違います。&lt;/p&gt;

&lt;p&gt;何もかもがオブジェクトなので、配列に対してメソッド呼び出しができます:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @b = @a.sort;
@b.elems;                   # 要素数
if @b &amp;gt; 2 { say "yes" }     # まだ動く
@b.end                      # 末尾要素のインデックス。$#arrayの代替
my @c = @b.map({$_ * 2 });  # mapはメソッドにもあります
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;従来の&lt;code&gt;qw(...)&lt;/code&gt;クォート生成の略記法があります:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @methods = &amp;lt;shift unshift push pop end delete sort map&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;ハッシュ&lt;/h3&gt;

&lt;p&gt;Perl5のハッシュはリストコンテキストでは偶数サイズのリストでしたが、Perl6のハッシュはペアのリストです。
ペアはサブルーチンの名前付き引数のような他の使い道もありますが、それについてはもっと後で出てきます。&lt;/p&gt;

&lt;p&gt;配列同様シジルは添字を指定したときも変わりませんし、ハッシュに対して呼び出せるメソッドもあります。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my %drinks =
    France  =&amp;gt; 'Wine',
    Bavaria =&amp;gt; 'Beer',
    USA     =&amp;gt; 'Coke';

say "The people in France love ",  %drinks{'France'};
my @countries = %drinks.keys.sort;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;%hash{...}&lt;/code&gt;でハッシュの要素にアクセスするとき、キーがPerl5のように自動でクォートされない点に注意して下さい。
&lt;code&gt;%hash{foo}&lt;/code&gt;は添字&lt;code&gt;"foo"&lt;/code&gt;にアクセスせず、関数&lt;code&gt;foo()&lt;/code&gt;を呼び出します。
自動クォートはなくなったわけではなく、構文が変更されました:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say %drinks&amp;lt;Bavaria&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;おわりに&lt;/h3&gt;

&lt;p&gt;ほとんどの組み込み関数はメソッドとサブルーチンの両方があるので、&lt;code&gt;sort @array&lt;/code&gt;とも&lt;code&gt;@array.sort&lt;/code&gt;とも書くことができます。&lt;/p&gt;

&lt;p&gt;最後に&lt;code&gt;[...]&lt;/code&gt;と&lt;code&gt;{...}&lt;/code&gt;(項の直後に出てくるもの)は特別な構文のメソッド呼び出しに過ぎず、配列やハッシュに結びついてはいないことを覚えておいて下さい。つまりこれらは、特定のシジルにも結びついていないということです。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $a = [1, 2, 3];
say $a[2];          # 3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これはつまり、デリファレンスのための特別な構文が必要ないということ、また配列やハッシュ、サブルーチンとして同時にふるまうようなオブジェクトが作れるということです。&lt;/p&gt;

&lt;h2&gt;SEE ALSO&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://perlcabal.org/syn/S02.html"&gt;http://perlcabal.org/syn/S02.html&lt;/a&gt;, &lt;a href="http://perlcabal.org/syn/S29.html"&gt;http://perlcabal.org/syn/S29.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-2238150778338503343?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/2238150778338503343/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6_12.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2238150778338503343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2238150778338503343'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6_12.html' title='Perl 5 to 6 - 文字列、配列、ハッシュ'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-602724568051191759</id><published>2011-02-11T23:34:00.013+09:00</published><updated>2011-03-05T01:26:49.389+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='perl-5-to-6'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Perl 5 to 6 - イントロダクション</title><content type='html'>&lt;p&gt;これはMoritz Lenz氏のWebサイト&lt;a href="http://perlgeek.de/"&gt;Perlgeek.de&lt;/a&gt;で公開されているブログ記事&lt;a href="http://perlgeek.de/blog-en/perl-5-to-6/00-intro.html"&gt;"Perl 5 to 6" - Introduction&lt;/a&gt;の日本語訳です。&lt;/p&gt;

&lt;p&gt;原文は&lt;a href="http://creativecommons.org/licenses/by/3.0/de/"&gt;Creative Commons Attribution 3.0 Germany&lt;/a&gt;に基づいて公開されています。&lt;/p&gt;

&lt;p&gt;本エントリには&lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons Attribution 3.0 Unported&lt;/a&gt;を適用します。&lt;/p&gt;

&lt;p&gt;Original text: Copyright&amp;#xA9; 2008-2010 Moritz Lenz&lt;/p&gt;

&lt;p&gt;Japanese translation: Copyright&amp;#xA9; 2011 SATOH Koichi&lt;/p&gt;

&lt;h2&gt;NAME&lt;/h2&gt;

&lt;p&gt;"Perl 5 to 6" - イントロダクション&lt;/p&gt;

&lt;h2&gt;SYNOPSIS&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;Perl6を学ぶ (もし既にPerl5を知っているなら)
Perl6の愛で方を学ぶ
理由を知る
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;DESCRIPTION&lt;/h2&gt;

&lt;p&gt;Perl6は十分にドキュメント化されていません。(仕様書を別にすれば)コンパイラを書くことの方がユーザ向けのドキュメントを用意することより急を要すると思われていることを鑑みれば、これは驚くべきことではありません。&lt;/p&gt;

&lt;p&gt;残念なことですが、つまりこれはPerl6を学ぶことが容易とは言えないということで、仕様書やらIRCやらテストスイートからPerl6を学ぼうとする動機を見つけるくらいの強い関心がないと駄目だということです。&lt;/p&gt;

&lt;p&gt;筆者が"Perl 5 to 6"(良い名前がない)と呼ぶことにしたこのプロジェクトは、短い記事の連載でこのギャップを埋めることを目的にしています。&lt;/p&gt;

&lt;p&gt;それぞれのレッスンはかなりテーマを絞り、短い例を使って2、3の最も重要な点を説明しようと思います。また、何故Perl5と6で物事が変わったのか、何故それが重要なのかも説明します。レッスンを読めば、Synopsis(Perl6の英知すべての規範的なソースです)を基本的に理解するのに十分な知識が得られるようにしたいと思います。&lt;/p&gt;

&lt;p&gt;読み易さを維持するために、各レッスンは200行ないし1000語(訳注:原文基準)を越えないものとします(ただしこれは緩い制限です)。&lt;/p&gt;

&lt;p&gt;恐らくレッスンはプログラミング言語を学ぶには短過ぎるでしょうが、言語設計の輪郭を描き出し、言語を学ばずともその美しさが感じられるようにしたいと思います。&lt;/p&gt;

&lt;h2&gt;IT'S NOT&lt;/h2&gt;

&lt;p&gt;これはPerl5プログラムのPerl6移行ガイドではありません。差異の包括的なリストでもありません。もしそのようなものを探しているなら、&lt;a href="http://perlcabal.org/syn/Differences.html"&gt;Perl6::Perl5::Differences&lt;/a&gt;を見て下さい。&lt;/p&gt;

&lt;p&gt;また現在の実装ではなく、仕様上の言語向けに書いています。&lt;/p&gt;

&lt;h2&gt;ROADMAP&lt;/h2&gt;

&lt;p&gt;既に書かれたか、準備中のもの:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;イントロダクション&lt;/li&gt;
&lt;li&gt;文字列、配列、ハッシュ&lt;/li&gt;
&lt;li&gt;型&lt;/li&gt;
&lt;li&gt;制御構造&lt;/li&gt;
&lt;li&gt;サブルーチンとシグネチャ&lt;/li&gt;
&lt;li&gt;オブジェクトとクラス&lt;/li&gt;
&lt;li&gt;コンテキスト&lt;/li&gt;
&lt;li&gt;ルール(正規表現)&lt;/li&gt;
&lt;li&gt;ジャンクション&lt;/li&gt;
&lt;li&gt;比較とスマートマッチ&lt;/li&gt;
&lt;li&gt;コンテナとバインディング&lt;/li&gt;
&lt;li&gt;基本的な演算&lt;/li&gt;
&lt;li&gt;遅延性 (-)&lt;/li&gt;
&lt;li&gt;カスタム演算子 (-)&lt;/li&gt;
&lt;li&gt;MAINサブルーチン&lt;/li&gt;
&lt;li&gt;ツイジル(Twigils)&lt;/li&gt;
&lt;li&gt;列挙&lt;/li&gt;
&lt;li&gt;Unicode (-)&lt;/li&gt;
&lt;li&gt;スコープ&lt;/li&gt;
&lt;li&gt;もっと正規表現&lt;/li&gt;
&lt;li&gt;XML用の正規表現&lt;/li&gt;
&lt;li&gt;サブセット型&lt;/li&gt;
&lt;li&gt;実装の現状&lt;/li&gt;
&lt;li&gt;クォートと構文解析 (-)&lt;/li&gt;
&lt;li&gt;縮約メタ演算子&lt;/li&gt;
&lt;li&gt;交差メタ演算子&lt;/li&gt;
&lt;li&gt;例外と制御例外&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(Rakudoにほとんど、あるいは全く実装されていない機能には(-)が付いています)&lt;/p&gt;

&lt;p&gt;書きたいと思っているが、筆者がまた十分に理解できていないこと:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;マクロ&lt;/li&gt;
&lt;li&gt;メタオブジェクトプログラミング&lt;/li&gt;
&lt;li&gt;並列性&lt;/li&gt;
&lt;li&gt;IO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;言及したいと思っているが、どこに入れるべきか迷っているもの:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.perlメソッド&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;これらのレッスンが時代遅れにならないよう、時々更新していくつもりです。
(訳注: 翻訳もできるだけ追随しようと思います。更新されてなかったらコメントなどで連絡をば)&lt;/p&gt;

&lt;h2&gt;AUTHOR&lt;/h2&gt;

&lt;p&gt;Moritz Lenz, &lt;a href="http://perlgeek.de/"&gt;http://perlgeek.de/&lt;/a&gt;, &lt;a href="&amp;#x6D;&amp;#x61;&amp;#105;&amp;#x6C;&amp;#116;&amp;#x6F;:&amp;#x6D;&amp;#111;&amp;#114;&amp;#105;&amp;#x74;&amp;#x7A;&amp;#64;f&amp;#97;&amp;#x75;&amp;#x69;&amp;#x32;&amp;#107;&amp;#51;&amp;#x2E;&amp;#x6F;&amp;#x72;&amp;#103;"&gt;&amp;#x6D;&amp;#111;&amp;#114;&amp;#105;&amp;#x74;&amp;#x7A;&amp;#64;f&amp;#97;&amp;#x75;&amp;#x69;&amp;#x32;&amp;#107;&amp;#51;&amp;#x2E;&amp;#x6F;&amp;#x72;&amp;#103;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;LINKS&lt;/h2&gt;

&lt;p&gt;他のドキュメントが&lt;a href="http://perl6.org/documentation/"&gt;http://perl6.org/documentation/&lt;/a&gt;で公開されています。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-602724568051191759?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/602724568051191759/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/602724568051191759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/602724568051191759'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2011/02/perl5perl6-perl-5-to-6.html' title='Perl 5 to 6 - イントロダクション'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-4757790336389286324</id><published>2009-07-16T21:13:00.006+09:00</published><updated>2011-02-18T08:36:37.015+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Perl - -CスイッチでPerlIOレイヤを操作</title><content type='html'>&lt;h2&gt;要約&lt;/h2&gt;

&lt;p&gt;マルチバイト文字を扱うワンライナはとりあえず-CSDとでもしておくと安心。&lt;/p&gt;

&lt;h2&gt;長文&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://ja.doukaku.org/"&gt;どう書く？org&lt;/a&gt;で&lt;a href="http://ja.doukaku.org/275/"&gt;バイナリクロック&lt;/a&gt;のお題に&lt;a href="http://ja.doukaku.org/comment/9329/"&gt;解答したら&lt;/a&gt;、あの&lt;a href="http://blog.livedoor.jp/dankogai/"&gt;小飼弾氏&lt;/a&gt;が&lt;a href="http://ja.doukaku.org/comment/9367/"&gt;さらに短くして下さいました&lt;/a&gt;。うはー!&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;perl -CIO -Mutf8 -le 'print for map { $_ = sprintf "%06b", $_; tr/01/□■/; $_ } (localtime)[2,1];'
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Perl5.8対応(そうか、-lで&lt;code&gt;$\&lt;/code&gt;出力だった)はともかく-Cスイッチって何ぞや、と思ったのでperldoc &lt;a href="http://perldoc.perl.org/perlrun.html"&gt;perlrun&lt;/a&gt;：&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;−C [number/list]
     The "−C" flag controls some of the Perl Unicode features.&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;「Perl5.8.1より前はWin32のワイド版APIを使うためのスイッチだったけど、誰も使わなかったから使い回すことにしたよ」とか中々楽しいことが書いてあり、現在はPerlIOレイヤを操作するスイッチになっているそうです。&lt;/p&gt;

&lt;p&gt;以下簡単な説明。&lt;/p&gt;

&lt;h3&gt;-C(I|O|E|S)&lt;/h3&gt;

&lt;p&gt;-C(I|O|E)はそれぞれ標準(入力|出力|エラー出力)のPerlIOレイヤをUTF-8に設定するオプションです。つまり次のコードと等価になります：&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt; binmode STDIN, ':utf8';  # -CI
 binmode STDOUT, ':utf8'; # -CO
 binmode STDERR, ':utf8'; # -CE
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;また-CSオプションで、これらをまとめて指定できます。&lt;/p&gt;

&lt;h3&gt;-C(i|o|D)&lt;/h3&gt;

&lt;p&gt;-C(i|o)はそれぞれ読み出し(&amp;lt;)、書き込み(&gt;)用に開くファイルハンドルに適用されるデフォルトのPerlIOレイヤをUTF-8に指定します。-CDは両者の一括指定。それぞれ&lt;code&gt;open&lt;/code&gt;プラグマを使った以下のコードと等価です：&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt; use open IN =&amp;gt; ':utf8';  # -Ci
 use open OUT =&amp;gt; ':utf8'; # -Co
 use open IO =&amp;gt; ':utf8';  # -CD
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;-CA&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;@ARGV&lt;/code&gt;の内容にUTF-8フラグを立てます。コマンドライン引数でUnicode文字列を渡す場合(あるか？)に。&lt;/p&gt;

&lt;h3&gt;-CL&lt;/h3&gt;

&lt;p&gt;ロケールに関する環境変数&lt;code&gt;LC_ALL&lt;/code&gt;、&lt;code&gt;LC_TYPE&lt;/code&gt;、&lt;code&gt;LANG&lt;/code&gt;をこの順に見ていき、存在する最初の値が"UTF-8"であったときのみ-Cオプションの指定を有効にします。&lt;/p&gt;

&lt;p&gt;例えば-CSDALとすると、ロケールがUTF-8であった場合のみ-CSDAが有効になります。&lt;/p&gt;

&lt;h3&gt;-Ca&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;${^UTF8CACHE}&lt;/code&gt;を-1に設定します……よく分かりません。デバッグ用のオプションのようです。&lt;/p&gt;

&lt;p&gt;"to run the UTF−8 caching code in debugging mode."とあるので、&lt;code&gt;perl -d&lt;/code&gt;のデバッグ・セッション中でもUnicode文字列のキャッシングを有効にするとかそんな意味でしょうか。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-4757790336389286324?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/4757790336389286324/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/07/perl-cperlio.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4757790336389286324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4757790336389286324'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/07/perl-cperlio.html' title='Perl - -CスイッチでPerlIOレイヤを操作'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3076870553725459724</id><published>2009-07-12T22:15:00.000+09:00</published><updated>2009-07-12T22:16:04.004+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 43</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=43"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Let d&lt;sub&gt;1&lt;/sub&gt; be the 1&lt;sup&gt;st&lt;/sup&gt; digit, d&lt;sub&gt;2&lt;/sub&gt; be the 2&lt;sup&gt;nd&lt;/sup&gt; digit, and so on. In this way, we note the following:&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;d&lt;sub&gt;2&lt;/sub&gt;d&lt;sub&gt;3&lt;/sub&gt;d&lt;sub&gt;4&lt;/sub&gt;=406 is divisible by 2&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;3&lt;/sub&gt;d&lt;sub&gt;4&lt;/sub&gt;d&lt;sub&gt;5&lt;/sub&gt;=063 is divisible by 3&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;4&lt;/sub&gt;d&lt;sub&gt;5&lt;/sub&gt;d&lt;sub&gt;6&lt;/sub&gt;=635 is divisible by 5&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;5&lt;/sub&gt;d&lt;sub&gt;6&lt;/sub&gt;d&lt;sub&gt;7&lt;/sub&gt;=357 is divisible by 7&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;6&lt;/sub&gt;d&lt;sub&gt;7&lt;/sub&gt;d&lt;sub&gt;8&lt;/sub&gt;=572 is divisible by 11&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;7&lt;/sub&gt;d&lt;sub&gt;8&lt;/sub&gt;d&lt;sub&gt;9&lt;/sub&gt;=728 is divisible by 13&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;8&lt;/sub&gt;d&lt;sub&gt;9&lt;/sub&gt;d&lt;sub&gt;10&lt;/sub&gt;=289 is divisible by 17&lt;/li&gt;
  &lt;/ul&gt;
  
  &lt;p&gt;Find the sum of all 0 to 9 pandigital numbers with this property.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2043"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;d&lt;sub&gt;1&lt;/sub&gt;を1桁目, d&lt;sub&gt;2&lt;/sub&gt;を2桁目の数とし, 以下順にd&lt;sub&gt;n&lt;/sub&gt;を定義する. この記法を用いると次のことが分かる.&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;d&lt;sub&gt;2&lt;/sub&gt;d&lt;sub&gt;3&lt;/sub&gt;d&lt;sub&gt;4&lt;/sub&gt;=406は2で割り切れる&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;3&lt;/sub&gt;d&lt;sub&gt;4&lt;/sub&gt;d&lt;sub&gt;5&lt;/sub&gt;=063は3で割り切れる&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;4&lt;/sub&gt;d&lt;sub&gt;5&lt;/sub&gt;d&lt;sub&gt;6&lt;/sub&gt;=635は5で割り切れる&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;5&lt;/sub&gt;d&lt;sub&gt;6&lt;/sub&gt;d&lt;sub&gt;7&lt;/sub&gt;=357は7で割り切れる&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;6&lt;/sub&gt;d&lt;sub&gt;7&lt;/sub&gt;d&lt;sub&gt;8&lt;/sub&gt;=572は11で割り切れる&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;7&lt;/sub&gt;d&lt;sub&gt;8&lt;/sub&gt;d&lt;sub&gt;9&lt;/sub&gt;=728は13で割り切れる&lt;/li&gt;
  &lt;li&gt;d&lt;sub&gt;8&lt;/sub&gt;d&lt;sub&gt;9&lt;/sub&gt;d&lt;sub&gt;10&lt;/sub&gt;=289は17で割り切れる&lt;/li&gt;
  &lt;/ul&gt;
  
  &lt;p&gt;このような性質をもつ0から9のPandigital数の総和を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://outer-inside.blogspot.com/2009/07/project-euler-problem-41.html"&gt;Problem 41&lt;/a&gt;と同様に&lt;a href="http://ja.wikipedia.org/wiki/%E3%83%91%E3%83%B3%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E6%95%B0"&gt;Pandigital数&lt;/a&gt;を作るだけです。途中で枝切りして無駄な計算を省いています。&lt;/p&gt;

&lt;p&gt;除数を保持する配列は一応定数にしてみました。定数の宣言には標準プラグマに&lt;a href="http://search.cpan.org/search?query=constant&amp;amp;mode=all"&gt;constant&lt;/a&gt;がありますが、コードが分かり易い&lt;a href="http://search.cpan.org/search?query=Attribute%3A%3AConstant&amp;amp;mode=all"&gt;Attribute::Constant&lt;/a&gt;というCPANモジュールを使っています。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use Attribute::Constant;
use List::Util qw/sum/;
use Set::Object qw/set/;

my @divisors : Constant(2, 3, 5, 7, 11, 13, 17);
sub solutions(;$$);
sub solutions(;$$) {
  my ($num, $rest_digits) = @_;
  $num //= '';
  $rest_digits //= set(0 .. 9);
  my $len = length $num;
  return () if $len &amp;gt;= 4 and substr($num, -3, 3) % $divisors[$len - 4] != 0;
  return () if $num =~ /^0/;
  return ('') if $rest_digits-&amp;gt;is_null;

  my @solutions;
  for my $n ($rest_digits-&amp;gt;members) {
    $rest_digits-&amp;gt;remove($n);
    push @solutions, map { $n . $_ } solutions($num . $n, $rest_digits);
    $rest_digits-&amp;gt;insert($n);
  }
  return @solutions;
}

say sum solutions;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3076870553725459724?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3076870553725459724/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-43.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3076870553725459724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3076870553725459724'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-43.html' title='Project Euler - Problem 43'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-7087305776762466431</id><published>2009-07-06T22:41:00.000+09:00</published><updated>2009-07-06T22:42:26.878+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 42</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=42"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;By converting each letter in a word to a number corresponding to its alphabetical position and adding these values we form a word value. For example, the word value for SKY is 19 + 11 + 25 = 55 = t&lt;sub&gt;10&lt;/sub&gt;. If the word value is a triangle number then we shall call the word a triangle word.&lt;/p&gt;
  
  &lt;p&gt;Using &lt;a href="http://projecteuler.net/project/words.txt"&gt;words.txt&lt;/a&gt; (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, how many are triangle words?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2042"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;単語中のアルファベットを数値に変換した後に和をとる. この和を「単語の値」と呼ぶことにする. 例えば SKY は 19 + 11 + 25 = 55 = t&lt;sub&gt;10&lt;/sub&gt;である. 単語の値が三角数であるとき, その単語を三角語と呼ぶ.&lt;/p&gt;
  
  &lt;p&gt;16Kのテキストファイル&lt;a href="http://projecteuler.net/project/words.txt"&gt;word.txt&lt;/a&gt;中に約2000語の英単語が記されている. 三角語はいくつあるか?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;42問目!&lt;/p&gt;

&lt;p&gt;ちょっと拍子抜けするほど簡単です。三角数を片っ端から計算して連想配列に入れておき、文字列の値を計算して照合するだけです。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/sum/;

sub word_value($) {
  my $offset = ord('A') - 1;
  sum map { ord($_) - $offset } split //, uc shift;
}

sub tri_num($) {
  my $n = shift;
  $n * ($n + 1) / 2;
}

open my $words, '&amp;lt;', 'words.txt' or die $!;
my @words = map { /\"(\w+)\"/ } split /,/, do { local $/ = undef; &amp;lt;$words&amp;gt; };

my $n = 0;
my $curr_max = tri_num $n++;
my %tri_nums = ($curr_max =&amp;gt; 1);
say 0 + grep {
  my $word_val = word_value $_;
  $tri_nums{$curr_max = tri_num $n++} = 1 while $curr_max &amp;lt; $word_val;
  $tri_nums{$word_val};
} @words;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-7087305776762466431?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/7087305776762466431/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-42.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7087305776762466431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7087305776762466431'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-42.html' title='Project Euler - Problem 42'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-8982591251939879683</id><published>2009-07-06T03:00:00.003+09:00</published><updated>2009-07-06T03:18:51.402+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 41</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=41"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the largest n-digit pandigital prime that exists?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2041"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;n桁のPandigitalな素数の中で最大の数を答えよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;ある数が3の倍数のとき、その各桁を足し合わせた数もまた3の倍数であり、その逆もいえます：&lt;/p&gt;

&lt;p&gt;n = a&lt;sub&gt;m-1&lt;/sub&gt;a&lt;sub&gt;m-2&lt;/sub&gt;...a&lt;sub&gt;0&lt;/sub&gt;&lt;br /&gt;
= a&lt;sub&gt;m-1&lt;/sub&gt;×10&lt;sup&gt;m-1&lt;/sup&gt; + a&lt;sub&gt;m-2&lt;/sub&gt;×10&lt;sup&gt;m-2&lt;/sup&gt; + ... + a&lt;sub&gt;0&lt;/sub&gt;×10&lt;sup&gt;0&lt;/sup&gt;&lt;br /&gt;
= a&lt;sub&gt;m-1&lt;/sub&gt;×(1 + 999...9) + a&lt;sub&gt;m-2&lt;/sub&gt;×(1 + 99...9) + ... + a&lt;sub&gt;1&lt;/sub&gt;×(1 + 9) + a&lt;sub&gt;0&lt;/sub&gt;×1&lt;br /&gt;
= (a&lt;sub&gt;m-1&lt;/sub&gt; + a&lt;sub&gt;m-2&lt;/sub&gt; + ... + a&lt;sub&gt;0&lt;/sub&gt;) + a&lt;sub&gt;m-1&lt;/sub&gt;×(999...9) + a&lt;sub&gt;m-2&lt;/sub&gt;×(99...9) + ... + a&lt;sub&gt;1&lt;/sub&gt;×9&lt;br /&gt;
∴ nが3の倍数のとき、a&lt;sub&gt;m-1&lt;/sub&gt; + a&lt;sub&gt;m-2&lt;/sub&gt; + ... + a&lt;sub&gt;0&lt;/sub&gt;は3の倍数&lt;/p&gt;

&lt;p&gt;つまり1 + 2 + ... + mが3の倍数であったとすると、m桁のPandigital数の中に解は存在し得ないことが分かります。m = 8, 9のときがこの場合に該当するので、探索範囲を大きく減らせます。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/%E3%83%91%E3%83%B3%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E6%95%B0"&gt;Pandigital数&lt;/a&gt;を作る際に数値を重複なく選ぶため、&lt;a href="http://search.cpan.org/search?query=Set%3A%3AObject&amp;amp;mode=all"&gt;Set::Object&lt;/a&gt;というCPANモジュールを使って簡単な集合演算を行っています。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl;

use strict;
use warnings;
use feature qw/say state/;
use List::Util qw/sum/;
use List::MoreUtils qw/none/;
use Set::Object qw/set/;

sub is_prime($) {
  state %memos;
  my $n = shift;
  return 0 if $n &amp;lt; 2;
  return 1 if $n == 2;
  return 1 if $n == 3;
  return $memos{$n} if exists $memos{$n};
  $memos{$n} = none { $n % $_ == 0 } 2 .. sqrt $n;
}

my $prime_tails = set(1, 3, 7, 9);

sub max_pandigital_prime($;$$);
sub max_pandigital_prime($;$$) {
  my ($ndigits, $num, $rest_digits) = @_;
  $num //= '';
  $rest_digits //= set(1 .. $ndigits);

  return is_prime $num ? $num : undef if $rest_digits-&amp;gt;is_null;
  return undef if ($rest_digits * $prime_tails)-&amp;gt;is_null;

  for my $n (sort { $b &amp;lt;=&amp;gt; $a } $rest_digits-&amp;gt;members) {
    $rest_digits-&amp;gt;remove($n);
    my $answer = max_pandigital_prime($ndigits - 1, $num . $n, $rest_digits);
    return $answer if defined $answer;
    $rest_digits-&amp;gt;insert($n);
  }
  return undef;
}

my $answer;
for my $ndigits (reverse 1 .. 9) {
  next if sum(1 .. $ndigits) % 3 == 0;
  last if defined ($answer = max_pandigital_prime($ndigits));
}
say $answer;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-8982591251939879683?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/8982591251939879683/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-41.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8982591251939879683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8982591251939879683'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-41.html' title='Project Euler - Problem 41'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-930365708888729745</id><published>2009-07-02T23:26:00.001+09:00</published><updated>2009-07-18T15:40:37.981+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 40</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=40"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;An irrational decimal fraction is created by concatenating the positive integers:&lt;/p&gt;
  
  &lt;p&gt;0.123456789101112131415161718192021...&lt;/p&gt;
  
  &lt;p&gt;It can be seen that the 12&lt;sup&gt;th&lt;/sup&gt; digit of the fractional part is 1.&lt;/p&gt;
  
  &lt;p&gt;If d&lt;sub&gt;n&lt;/sub&gt; represents the n&lt;sup&gt;th&lt;/sup&gt; digit of the fractional part, find the value of the following expression.&lt;/p&gt;
  
  &lt;p&gt;d&lt;sub&gt;1&lt;/sub&gt; × d&lt;sub&gt;10&lt;/sub&gt; × d&lt;sub&gt;100&lt;/sub&gt; × d&lt;sub&gt;1000&lt;/sub&gt; × d&lt;sub&gt;10000&lt;/sub&gt; × d&lt;sub&gt;100000&lt;/sub&gt; × d&lt;sub&gt;1000000&lt;/sub&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2040"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;正の整数を順に連結して得られる以下の10進の無理数を考える:&lt;/p&gt;
  
  &lt;p&gt;0.123456789101112131415161718192021...&lt;/p&gt;
  
  &lt;p&gt;小数点第12位は1である.&lt;/p&gt;
  
  &lt;p&gt;d&lt;sub&gt;n&lt;/sub&gt;で小数点第n位の数を表す. d&lt;sub&gt;1&lt;/sub&gt; × d&lt;sub&gt;10&lt;/sub&gt; × d&lt;sub&gt;100&lt;/sub&gt; × d&lt;sub&gt;1000&lt;/sub&gt; × d&lt;sub&gt;10000&lt;/sub&gt; × d&lt;sub&gt;100000&lt;/sub&gt; × d&lt;sub&gt;1000000&lt;/sub&gt; を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;数列作って、繋げて、取り出して、掛け合わせる。おしまい。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/reduce/;

my $n = 0;
my $str = '';
$str .= $n++ while length $str &amp;lt;= 1_000_000;

our ($a, $b);
say reduce { $a * $b } map { substr $str, 10 ** $_, 1 } 0 .. 6;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-930365708888729745?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/930365708888729745/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-40.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/930365708888729745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/930365708888729745'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-40.html' title='Project Euler - Problem 40'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-1013127364519479460</id><published>2009-07-02T13:31:00.002+09:00</published><updated>2009-07-02T13:46:45.189+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 39</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=39"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If p is the perimeter of a right angle triangle with integral length sides, {a,b,c}, there are exactly three solutions for p = 120.&lt;/p&gt;
  
  &lt;p&gt;{20,48,52}, {24,45,51}, {30,40,50}&lt;/p&gt;
  
  &lt;p&gt;For which value of p ≤ 1000, is the number of solutions maximised?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2039"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;辺の長さが{a,b,c}と整数の3つ組である直角三角形を考え, その周囲の長さをpとする. p = 120のときには3つの解が存在する:&lt;/p&gt;
  
  &lt;p&gt;{20,48,52}, {24,45,51}, {30,40,50}&lt;/p&gt;
  
  &lt;p&gt;p &amp;lt; 1000 で解の数が最大になる p を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;問題の前提からp = a + b + cです。&lt;/p&gt;

&lt;p&gt;三平方の定理よりa&lt;sup&gt;2&lt;/sup&gt; + b&lt;sup&gt;2&lt;/sup&gt; = c&lt;sup&gt;2&lt;/sup&gt;で、p = a + b + c ⇒ c = p - (a + b)なので、cを消去して：&lt;/p&gt;

&lt;p&gt;a&lt;sup&gt;2&lt;/sup&gt; + b&lt;sup&gt;2&lt;/sup&gt; = (p - (a + b))&lt;sup&gt;2&lt;/sup&gt; = p&lt;sup&gt;2&lt;/sup&gt; - 2p(a + b) + a&lt;sup&gt;2&lt;/sup&gt; + 2ab + b&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;よってp&lt;sup&gt;2&lt;/sup&gt; - 2p(a + b) + 2ab = 0であり、a、bが解のときpは偶数であることが分かります。
またこれをbについて解くとb = (2ap - p&lt;sup&gt;2&lt;/sup&gt;) / 2(a - p)なので、aの値を定めればbの値は一意に決まることが分かります。
結局各pについてa &gt; bとなるまでaを一通り試すだけで良いことになります。&lt;/p&gt;

&lt;p&gt;実のところ答えの3つ組を計算する必要はなかったりしますが、答えを出力した上でその数を数える形にしています。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/reduce/;

sub solutions($) {
  my $p = shift;
  return () unless $p % 2 == 0;

  my @solutions;
  for my $i (1 .. $p - 1) {
    my $j = ($p * (2 * $i - $p)) / (2 * ($i - $p));
    last unless $i &amp;lt;= $j;
    push @solutions, [ $i, $j, sqrt($i ** 2 + $j ** 2) ] if $j == int $j;
  }
  return @solutions;
}

say map { $_-&amp;gt;{p} } reduce {
  $a-&amp;gt;{num_sols} &amp;gt; $b-&amp;gt;{num_sols} ? $a : $b
} map { { p =&amp;gt; $_, num_sols =&amp;gt; 0 + grep 1, solutions $_ } } 1 .. 999;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-1013127364519479460?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/1013127364519479460/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-39.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1013127364519479460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1013127364519479460'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/07/project-euler-problem-39.html' title='Project Euler - Problem 39'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-2255602499396460902</id><published>2009-06-27T19:59:00.004+09:00</published><updated>2009-06-28T09:59:57.908+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 38</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=38"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the largest 1 to 9 pandigital 9-digit number that can be formed as the concatenated product of an integer with (1,2, ... , n) where n &gt; 1?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2038"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;整数と(1,2,...,n) (n &gt; 1) との連結積として得られる9桁のPandigital数の中で最大のものを答えよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;乗数が1, 2, ..., n (n &gt; 1)で桁数は9なので、被乗数mは1から9999の範囲です。
範囲が分かれば後は簡単で、m×1から順に積を連結していって、丁度9桁となったときにPandigital数であればいいわけです。
&lt;a href="http://ja.wikipedia.org/wiki/%E3%83%91%E3%83%B3%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E6%95%B0"&gt;Pandigital数&lt;/a&gt;を定義通り考えれば「1から9のすべての数字が1回以上現れる数」ですが、この問題では桁数の制約からいずれの数字も1回ずつしか現れないため、「同じ数字が重複して出現せず、0が現れない数」に読み替えることができます。Perlだとこちらの方が正規表現マッチングが高速でした。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/max/;

say max map {
  my $cat = '';
  for (my $mul = 1; length $cat &amp;lt; 9; $cat .= $_ * $mul++) {}
  (length $cat == 9 and $cat !~ /0/ and $cat !~ /(\d).*\1/) ? $cat : ()
} 1 .. 9999;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-2255602499396460902?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/2255602499396460902/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-38.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2255602499396460902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2255602499396460902'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-38.html' title='Project Euler - Problem 38'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-4131578668915219902</id><published>2009-06-27T02:40:00.002+09:00</published><updated>2009-06-27T02:46:12.846+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 37</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=37"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of the only eleven primes that are both truncatable from left to right and right to left.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2037"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;右から切り詰めても左から切り詰めても素数になるような素数は11個しかない. 総和を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;考え方は&lt;a href="http://outer-inside.blogspot.com/2009/06/project-euler-problem-35.html"&gt;Problem 35&lt;/a&gt;と同じで、切り詰めていくと途中で合成数になることが分かっている数を最初に除外しています。
0、4、6、8のいずれかの数字を含む場合は明らかに途中で偶数になりますが、2と5は少し特別で、数の一番上の桁にのみ現れた場合は除外できません。何故なら：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;左から切り詰めたときは最初に取り除かれるので関係がない。&lt;/li&gt;
&lt;li&gt;右から切り詰めていって最後の1桁になったとき、2と5は素数である。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;からです。具体的には23と53がこのケースに該当するので、間違って除外すると処理が終わりません。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say state/;
use List::Util qw/sum/;
use List::MoreUtils qw/all none/;

sub is_prime($) {
  state %memos;
  my $n = shift;
  return 0 if $n &amp;lt; 2;
  return 1 if $n == 2;
  return 1 if $n == 3;
  return $memos{$n} if exists $memos{$n};
  $memos{$n} = none { $n % $_ == 0 } 2 .. sqrt $n;
}

sub is_truncatable_prime($) {
  my $n = shift;
  return 0 if length $n == 1;
  return 0 if $n =~ /[0468]/;
  return 0 if $n =~ /.[25]/;
  return 0 unless is_prime $n;
  all {
    is_prime substr($n, $_) and is_prime substr($n, 0, -$_)
  } 1 .. length($n) - 1;
}

my @truncatables;
for (my $i = 11; @truncatables != 11; $i += 2) {
  push @truncatables, $i if is_truncatable_prime $i;
}
say sum @truncatables;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-4131578668915219902?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/4131578668915219902/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-37.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4131578668915219902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4131578668915219902'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-37.html' title='Project Euler - Problem 37'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-4592126909662805317</id><published>2009-06-24T00:35:00.004+09:00</published><updated>2009-07-06T01:56:22.029+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 36</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=36"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2036"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;100万未満で10進でも2進でも回文数になるような数の総和を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;nで割り切れる数はn進法で表すと下の桁が0になります(e.g. 100&lt;sub&gt;10&lt;/sub&gt;、32=20&lt;sub&gt;16&lt;/sub&gt;、8=1000&lt;sub&gt;2&lt;/sub&gt;)。
このような数は反転させると(先頭の0は無視するので)桁数が変わってしまうため、回文数になりません。よってこのような数は最初に除外できます。&lt;/p&gt;

&lt;p&gt;この問題の場合、2か10で割り切れる数は解にならないことが分かります。10で割り切れるときは当然2でも割り切れるので、実際には2で割り切れるか調べれば十分です。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/sum/;

sub is_palindromic($) {
  my $n = shift;
  $n eq reverse $n;
}

say sum grep {
  is_palindromic $_ and is_palindromic sprintf '%b', $_;
} grep { $_ % 2 != 0 } 1 .. 1_000_000;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;追記&lt;/h3&gt;

&lt;p&gt;値の範囲ですが、1,000,000まで探索する必要はありませんでした。
1から999まで探索して、それを反転させた数値と連結すれば偶数桁の回文数、その間に1つ数字を入れれば奇数桁の回文数が得られるので、探索範囲を絞った上に10進数の回文数判定も省けます。&lt;/p&gt;

&lt;p&gt;少し長いですが、70倍ほど高速化できました。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;use Scalar::Util qw/looks_like_number/;
say sum grep {
  $_ &amp;lt;= 1_000_000 and is_palindromic sprintf '%b', $_;
} map {
  my $half = $_;
  map {
    $half . $_ . reverse($half)
  } (looks_like_number $half) ? ('', ($half &amp;gt; 100) ? () : 0 .. 9) : 0 .. 9;
} grep {
  not looks_like_number $_ or /^[13579]/;
} ('', 1 .. 999);
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-4592126909662805317?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/4592126909662805317/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-36.html#comment-form' title='2 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4592126909662805317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4592126909662805317'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-36.html' title='Project Euler - Problem 36'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3777505849733360771</id><published>2009-06-24T00:02:00.003+09:00</published><updated>2009-07-15T01:52:47.369+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 35</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=35"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How many circular primes are there below one million?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2035"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;100万未満の巡回素数は何個か?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;回転させた数値がすべて素数ということは、すべての桁が奇数でなければいけません(ただし2を除く)。&lt;/p&gt;

&lt;h3&gt;追記&lt;/h3&gt;

&lt;p&gt;匿名氏にコメントでご指摘頂いたのでコードを一部修正しました。
いずれかの桁に5がある場合も、回転させると必ず5の倍数が現れるので除外できます。&lt;/p&gt;

&lt;h3&gt;もっと追記&lt;/h3&gt;

&lt;p&gt;前の修正に間違いが入っているのをご指摘頂いたので修正しました。
5自体は素数なので、巻き添えで除外してはいけません。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say state/;
use List::MoreUtils qw/all none/;

sub is_prime($) {
  state %memos;
  my $n = shift;
  return 0 if $n &amp;lt; 2;
  return 1 if $n == 2;
  return 1 if $n == 3;
  return $memos{$n} if exists $memos{$n};
  $memos{$n} = none { $n % $_ == 0 } 2 .. sqrt $n;
}

sub rotate($) {
  my $n = shift;
  substr($n, 1) . substr($n, 0, 1);
}

sub rotations($) {
  my $n = shift;
  my %seen = ($n =&amp;gt; 1);
  $seen{$n} = 1 until exists $seen{$n = rotate $n};
  keys %seen;
}

sub is_circular_prime($) {
  state %memos;
  my $n = shift;
  return 0 if $n =~ /[024568]/ and $n != 2 and $n != 5;
  return $memos{$n} if exists $memos{$n};

  my @rotations = rotations $n;
  my $is_circular_prime = all { is_prime $_ } @rotations;
  (@memos{@rotations} = ($is_circular_prime) x @rotations)[0];
}

say 0 + grep { is_circular_prime $_ } 1 .. 1_000_000;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3777505849733360771?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3777505849733360771/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-35.html#comment-form' title='4 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3777505849733360771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3777505849733360771'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-35.html' title='Project Euler - Problem 35'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-6436878680370717502</id><published>2009-06-21T23:11:00.000+09:00</published><updated>2009-06-21T23:12:46.153+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 34</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=34"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of all numbers which are equal to the sum of the factorial of their digits.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2034"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;各桁の数の階乗の和が自分自身と一致するような数の総和を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://outer-inside.blogspot.com/2009/05/project-euler-problem-30.html"&gt;Problem 30&lt;/a&gt;とほぼ同じ問題なので、その時の解答を基にして考えます。&lt;/p&gt;

&lt;p&gt;前回の問題と違うのは、0! = 1なので0を含む数字を含まない数字と同一視できない点です。
そこで正規化の際に0を省くのをやめて、例えば251と2501はそれぞれ125と0125として別に扱うことにします。&lt;/p&gt;

&lt;p&gt;また0! = 1!なので、例えば110と100のように各桁の階乗の和が同じになる数が存在し、これを重複して数えないようにしなければなりません。
既に数えた値を連想配列で覚えておいてもいいのですが、&lt;a href="http://search.cpan.org/search?query=List%3A%3AMoreUtils&amp;amp;mode=all"&gt;List::MoreUtils&lt;/a&gt;の&lt;code&gt;uniq&lt;/code&gt;関数で重複要素を前もって削除する方が高速でした。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl;

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/sum reduce/;
use List::MoreUtils qw/uniq/;

sub factorial($) {
  our ($a, $b);
  my $n = shift;
  return 1 if $n == 0;
  return reduce { $a * $b } 1 .. $n;
}

my @facts = map { factorial $_ } 0 .. 9;
my $max_digits;
for ($max_digits = 1;
     10 ** $max_digits &amp;lt;= $max_digits * $facts[9];
     $max_digits++) {}

my @sum_dicts = ({}, { map { ($_ =&amp;gt; $facts[$_]) } 0 .. 9 });
until ($#sum_dicts == $max_digits) {
  push @sum_dicts, { map {
    my $prev_key = $_;
    my $last_digit = substr $prev_key, -1, 1;
    map {
      ("$prev_key$_" =&amp;gt; $sum_dicts[-1]{$prev_key} + $facts[$_])
    } $last_digit .. 9;
  } keys %{ $sum_dicts[-1] } };
}

say sum grep {
  my $sorted = join '', sort split //;
  $_ == $sum_dicts[length $sorted]{$sorted} and $_ != 1 and $_ != 2;
} uniq map { values %$_ } @sum_dicts;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-6436878680370717502?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/6436878680370717502/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-34.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6436878680370717502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6436878680370717502'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-34.html' title='Project Euler - Problem 34'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5315242378053073836</id><published>2009-06-15T00:19:00.000+09:00</published><updated>2009-06-15T00:23:56.768+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 33</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=33"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The fraction 49/98 is a curious fraction, as an inexperienced mathematician in attempting to simplify it may incorrectly believe that 49/98 = 4/8, which is correct, is obtained by cancelling the 9s.&lt;/p&gt;
  
  &lt;p&gt;We shall consider fractions like, 30/50 = 3/5, to be trivial examples.&lt;/p&gt;
  
  &lt;p&gt;There are exactly four non-trivial examples of this type of fraction, less than one in value, and containing two digits in the numerator and denominator.&lt;/p&gt;
  
  &lt;p&gt;If the product of these four fractions is given in its lowest common terms, find the value of the denominator.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2033"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;49/98は面白い分数である. 「分子・分母の9をキャンセルしたので 49/98 = 4/8 が得られた」と経験を積んでいない数学者が誤って思い込んでしまうかもしれないからである.&lt;/p&gt;
  
  &lt;p&gt;我々は 30/50 = 3/5 のようなタイプは自明な例だとする.&lt;/p&gt;
  
  &lt;p&gt;1より小さく分子・分母がともに2桁の数になるような自明でない分数は 4個ある.&lt;/p&gt;
  
  &lt;p&gt;その4個の分数の積が約分された形で与えられたとき, 分母の値を答えよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;どうも「自明でない分数」の基準がよく分かりませんが、「分子・分母に共通する数字を取り除いたとき、元の分数と同じ値になるような分数(ただし分子・分母が10の倍数である場合を除く)」みたいです。&lt;/p&gt;

&lt;p&gt;分数を&lt;code&gt;(numerator, denominator)&lt;/code&gt;というリストの形で扱うことにして、「共通する数字を取り除いた1桁/1桁の分数で、通分した結果が元の分数のそれと等しい」という長ったらしい述語&lt;code&gt;is_non_trivial&lt;/code&gt;を作りました。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/reduce/;
use List::MoreUtils qw/none/;

sub gcd {
  my ($m, $n) = @_;
  ($m, $n) = ($n, $m) if $m &amp;lt; $n;
  my $r = $m % $n;
  $r == 0 ? $n : gcd($n, $r);
}

sub reduce_fraction {
  my ($num, $den) = @_;
  my $gcd = gcd($num, $den);
  map { $_ / $gcd } ($num, $den);
}

sub is_non_trivial {
  my ($num, $den) = @_;
  return 0 if $num % 10 == 0 or $den % 10 == 0;

  my @ns = split //, $num;
  my @ds = split //, $den;
  my @uns = grep { my $n = $_; none { $_ == $n } @ds } @ns;
  my @uds = grep { my $d = $_; none { $_ == $d } @ns } @ds;
  return 0 unless @uns == 1 and @uds == 1;

  my ($rn, $rd) = reduce_fraction($num, $den);
  my ($urn, $urd) = reduce_fraction(@uns, @uds);
  $rn == $urn and $rd == $urd;
}

my @product = @{
  reduce {
    [ $a-&amp;gt;[0] * $b-&amp;gt;[0], $a-&amp;gt;[1] * $b-&amp;gt;[1] ]
  } map {
    my $den = $_;
    map { [$_, $den] } grep { is_non_trivial($_, $den) } 10 .. $den - 1;
  } 11 .. 99
};
say +(reduce_fraction(@product))[1];
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5315242378053073836?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5315242378053073836/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-33.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5315242378053073836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5315242378053073836'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-33.html' title='Project Euler - Problem 33'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-7855372129295772753</id><published>2009-06-13T20:41:00.001+09:00</published><updated>2009-06-14T23:53:50.890+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 32</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=32"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of all products whose multiplicand/multiplier/product identity can be written as a 1 through 9 pandigital.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2032"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;掛けられる数/掛ける数/積に1から9の数が1回ずつ出現するような積の総和を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;n桁×m桁の数の積はn+m-1桁かn+m桁になる(e.g. 10×10=100, 99×99=9,801)ので、桁数の合計が9になるとき、積の桁数は4桁であることが分かります。つまり、調べる積の範囲は1,000から9,999までとなります。&lt;/p&gt;

&lt;p&gt;あとは数字が重複していないかどうかの判定ですが、積・乗数・被乗数を並べて数字列を作り、小さい順に並べ替えて123456789になれば重複していないことになります。
例えば4396=28×157の場合、並べて書くと439628157という数字列ができます。これを並べ替えると123456789になりますから、4396は答えの1つであることが分かります。&lt;/p&gt;

&lt;p&gt;乗数の取り得る範囲は1から積の平方根の間ですが、1の時は積と被乗数が同じになるので明らかに答えではありません。従って2から開始すると少しだけ早くなります。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/sum/;
use List::MoreUtils qw/any/;

say sum grep {
  my $n = $_;
  any {
    join('', sort split //, $n . $_ . $n / $_) eq '123456789';
  } grep { $n % $_ == 0 } 2 .. sqrt $n;
} 1000 .. 9999;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-7855372129295772753?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/7855372129295772753/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-32.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7855372129295772753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7855372129295772753'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/06/project-euler-problem-32.html' title='Project Euler - Problem 32'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-4215435759941736860</id><published>2009-05-14T13:14:00.000+09:00</published><updated>2009-05-14T13:15:33.979+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 31</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=31"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How many different ways can £2 be made using any number of coins?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2031"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;いくらかの硬貨を使って2ポンドを作る方法はいくつあるでしょうか?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;ポンドとペンスを別々に扱うのは面倒と無駄以外の何者でもないので、単位をペンスに統一します。よって問題は合計が200ペンスとなるコインの組み合わせは何通りあるかです。&lt;/p&gt;

&lt;p&gt;コインを昇順にC&lt;sub&gt;i&lt;/sub&gt;(i = 0, 1, 2, ..., 7)と番号づけることにします。
合計nペンスとなるC&lt;sub&gt;k&lt;/sub&gt;以下のコインを使った組み合わせをcc(n, k)と表すと、次のようになります：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;cc(0, k) = 1&lt;/li&gt;
&lt;li&gt;cc(n, 1) = 1&lt;/li&gt;
&lt;li&gt;cc(n, k) = Σ(cc(n - iC&lt;sub&gt;k&lt;/sub&gt;, k - 1))、ただしi ∈ { 0 , 1, 2, ..., floor(n / C&lt;sub&gt;k&lt;/sub&gt;) }&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;副問題は同じものが何度も出てくるのでメモ化しています。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say state/;
use List::Util qw/sum/;

sub coin_comb($;$);
{
  my @coins = (1, 2, 5, 10, 20, 50, 100, 200);
  sub coin_comb($;$) {
    state %memos;
    my ($currency, $coin_idx) = @_;
    $coin_idx //= $#coins;

    return $memos{$currency, $coin_idx} if exists $memos{$currency, $coin_idx};
    return 1 if $currency == 0;
    return 1 if $coin_idx == 0;

    use integer;
    $memos{$currency, $coin_idx} = sum map {
      coin_comb($currency - $coins[$coin_idx] * $_, $coin_idx - 1);
    } 0 .. $currency / $coins[$coin_idx];
  }
}
say coin_comb 200;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-4215435759941736860?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/4215435759941736860/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/05/project-euler-problem-31.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4215435759941736860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4215435759941736860'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/05/project-euler-problem-31.html' title='Project Euler - Problem 31'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-2652820638827893813</id><published>2009-05-14T11:48:00.001+09:00</published><updated>2009-05-14T13:11:31.268+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 30</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=30"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2030"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;各桁を5乗した和が元の数と一致するような数の総和を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;まず探索範囲の上限を定める必要があります。n桁の最大の整数a&lt;sub&gt;n&lt;/sub&gt; = 9&lt;sub&gt;n-1&lt;/sub&gt;9&lt;sub&gt;n-2&lt;/sub&gt;...9&lt;sub&gt;0&lt;/sub&gt;を考えると、その各桁の5乗の和はb&lt;sub&gt;n&lt;/sub&gt; = 9&lt;sup&gt;5&lt;/sup&gt;nと表せます。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a&lt;sub&gt;n+1&lt;/sub&gt; = 10a&lt;sub&gt;n&lt;/sub&gt; + 9&lt;/li&gt;
&lt;li&gt;b&lt;sub&gt;n+1&lt;/sub&gt; = b&lt;sub&gt;n&lt;/sub&gt; + 9&lt;sup&gt;5&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ですから、桁数nが大きくなるにつれてaがbよりも急激に大きくなるのが分かります。ある桁数n&lt;sub&gt;max&lt;/sub&gt;を超えると、常にa&lt;sub&gt;n&lt;sub&gt;max&lt;/sub&gt;&lt;/sub&gt; &gt; b&lt;sub&gt;n&lt;sub&gt;max&lt;/sub&gt;&lt;/sub&gt;が成立するので、両者が等しくなることはなくなります。
実際に調べるとn&lt;sub&gt;max&lt;/sub&gt;は6なので、探索範囲は高々0から999,999までとなります。&lt;/p&gt;

&lt;p&gt;各桁の乗数の和は、桁の並びに関わらず各桁の数のみによって決まります。例えば2501、5012、(0)215のいずれも同じb&lt;sub&gt;n&lt;/sub&gt;を持つので、これを別々に計算するのは時間の無駄です。
そこで、このような数をすべて同値と見なす正規化を考えます。手っ取り早く桁の並べ替えで良いでしょう。各桁を昇順に並べ替え、その上で先頭に1個以上0があったら取り除くという処理です。先ほどの例に挙げた数字をこの方法で正規化すると、いずれも125となります。&lt;/p&gt;

&lt;p&gt;この正規化された数のみを走査すれば良いわけですから、（0を含まない）n桁の数1つにつき同じ値をn!通り計算していたところが、1通りで済むことになります。&lt;/p&gt;

&lt;p&gt;処理の手順をまとめると次のようになります：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;全ての正規化された数に対してb&lt;sub&gt;n&lt;/sub&gt;を計算し、連想配列に格納しておく。&lt;/li&gt;
&lt;li&gt;連想配列に格納された値を1つ取り出し、a&lt;sub&gt;n&lt;/sub&gt;とする。&lt;/li&gt;
&lt;li&gt;a&lt;sub&gt;n&lt;/sub&gt;を正規化して連想配列から対応するb&lt;sub&gt;n&lt;/sub&gt;を引く。&lt;/li&gt;
&lt;li&gt;a&lt;sub&gt;n&lt;/sub&gt; = b&lt;sub&gt;n&lt;/sub&gt;であれば解に加える。&lt;/li&gt;
&lt;li&gt;連想配列の値を全て走査するまで2.に戻って繰り返す。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;下記のコードでは初期化の都合上、桁数ごとに連想配列を分けていますがアルゴリズム自体に違いはありません。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/sum/;

sub regularize($) {
  join '', grep { $_ != 0 } sort { $a &amp;lt;=&amp;gt; $b } split //, shift;
}

my $max_digits = 0;
my ($upper_limit, $sum);
do {
  $max_digits++;
  $upper_limit = 9 x $max_digits;
  $sum = $max_digits * (9 ** 5);
} while $upper_limit &amp;lt; $sum;

my @powers = map { $_ ** 5 } 0 .. 9;
my @sum_dicts = ({ '' =&amp;gt; 0 }, { map { ($_ =&amp;gt; $powers[$_]) } 1 .. 9 });
while ($#sum_dicts &amp;lt; $max_digits) {
  push @sum_dicts, { map {
    my $prev_key = $_;
    my $last_digit = substr $prev_key, -1, 1;
    map {
      ("$prev_key$_" =&amp;gt; $sum_dicts[-1]{$prev_key} + $powers[$_])
    } $last_digit .. 9;
  } keys %{ $sum_dicts[-1] } };
}
say sum grep {
  my $sorted = regularize $_;
  $_ == $sum_dicts[length $sorted]{$sorted};
} grep { $_ &amp;gt; 1 } map { values %$_ } @sum_dicts ;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-2652820638827893813?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/2652820638827893813/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/05/project-euler-problem-30.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2652820638827893813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2652820638827893813'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/05/project-euler-problem-30.html' title='Project Euler - Problem 30'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-7605045054256557102</id><published>2009-05-04T22:24:00.010+09:00</published><updated>2009-05-06T22:34:07.705+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 29</title><content type='html'>&lt;p&gt;こんばんはSekia the Liarです。更新頻度についての釈明はさておきえーとP.E. 29でしたね。はい、すいません。&lt;/p&gt;

&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=29"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Consider all integer combinations of a^(b) for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:
  （引用者による省略）
  How many distinct terms are in the sequence generated by a&lt;sup&gt;b&lt;/sup&gt; for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2029"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;2 ≤ a ≤ 5 と 2 ≤ b ≤ 5について, abを全て考えてみよう:
  （引用者による省略）
  2 ≤ a ≤ 100, 2 ≤ b ≤ 100 で同じことをしたときいくつの異なる項が存在するか?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;値の重複を取り除くにはハッシュを使うのが定石です。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;use strict;
use warnings;
use feature qw/say/;
use Math::BigInt;

my %pows;
for my $n (2 .. 100) {
  for my $i (2 .. 100) {
    $pows{ Math::BigInt-&amp;gt;new($n) ** $i } = 1;
  }
}
say scalar keys %pows;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;しかしPerlのメソッド解決オーバヘッドは結構でかいので、10,000個のMath::BigIntインスタンス生成は割と時間を食います。毎回Math::BigIntというのも芸がないし、少し頭を使って解いてみることにしました。&lt;/p&gt;

&lt;p&gt;a&lt;sup&gt;b&lt;/sup&gt; = (a&lt;sup&gt;n&lt;/sup&gt;)&lt;sup&gt;b/n&lt;/sup&gt;であることに着目しましょう。これは中学だか高校だかで習った通りです。ただし問題の範囲は整数なので、指数は2 ≤ b/n ≤ 100なる整数でなければなりません。つまりnはbの約数（ただしb自身を除く）です。&lt;/p&gt;

&lt;p&gt;この等号で結ばれたべき乗は同じ（つまり重複した）値を持ちます。&lt;/p&gt;

&lt;p&gt;例えば2&lt;sup&gt;12&lt;/sup&gt; = 4(=2&lt;sup&gt;2&lt;/sup&gt;)&lt;sup&gt;6&lt;/sup&gt; = 8(=2&lt;sup&gt;3&lt;/sup&gt;)&lt;sup&gt;4&lt;/sup&gt; = 16(=2&lt;sup&gt;4&lt;/sup&gt;)&lt;sup&gt;3&lt;/sup&gt; = 64(=2&lt;sup&gt;6&lt;/sup&gt;)&lt;sup&gt;2&lt;/sup&gt; = 4,096であり、他に4,096となるようなべき乗は整数の範囲ではなさそうです（証明してないので間違ってたら教えてください）。&lt;/p&gt;

&lt;p&gt;これをふまえると、等式が成り立つa、bの組のうちaが最小のもの（ここでa&lt;sub&gt;0&lt;/sub&gt;、b&lt;sub&gt;0&lt;/sub&gt;とおきましょう）が分かれば、残りのものはすべてa = a&lt;sub&gt;0&lt;/sub&gt;&lt;sup&gt;n&lt;/sup&gt;、b = b&lt;sub&gt;0&lt;/sub&gt;/nの形をしているはずです。したがって同じ値を持つa、bの組はすべてa&lt;sub&gt;0&lt;/sub&gt;、b&lt;sub&gt;0&lt;/sub&gt;から求められます。&lt;/p&gt;

&lt;p&gt;よってa&lt;sub&gt;0&lt;/sub&gt;、b&lt;sub&gt;0&lt;/sub&gt;のみを数えて、残りは重複として印をつけてスキップするようにすれば、重複のないべき乗の個数を数えることができます。&lt;/p&gt;

&lt;p&gt;ところで2 ≤ a&lt;sup&gt;n&lt;/sup&gt; ≤ 100、2 ≤ b/n ≤ 100という拘束条件にちょっとした注意が必要です。というのも、n = 1のときにこの条件を満足せず、nがある程度大きくなれば満足するa、bが存在するからです。
このような数を取りこぼさないためにはb/n ≤ 100 × floor(log&lt;sub&gt;n&lt;/sub&gt;100)（floorは床関数）までを探索し、b/n ≤ 100である間はnに1加えて何もせずスキップする、というような処理が必要になります。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use POSIX qw/floor/;

{
  my %memos;
  #returns divisors of $n (except $n itself) in numeric order
  sub divisors($) {
    my $n = shift;
    return @{ $memos{$n} } if exists $memos{$n};

    my @early = grep { $n % $_ == 0 } 2 .. floor sqrt $n;
    my @later = reverse map { $n / $_ } @early;
    shift @later if @later != 0 and $later[0] ** 2 == $n;

    return @{ $memos{$n} = [1, @early, @later] };
  }
}

sub logn($$) { my ($b, $n) = @_; (log $n) / (log $b) }

my %passed;
my $num_distincts = 0;
for my $n (2 .. 100) {
  my $max_i = 100 * floor logn($n, 100);
  for my $i (2 .. $max_i) {
    my $is_dist = 0;
    for my $d (divisors $i) {
      my ($m, $j) = ($n ** $d, $i / $d);
      next if $passed{$m, $j};
      next if $j &amp;gt; 100;
      last if $m &amp;gt; 100;

      $passed{$m, $j} = $is_dist = 1;
    }
    $num_distincts++ if $is_dist;
  }
}
say $num_distincts;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;蛇足な補足&lt;/h3&gt;

&lt;p&gt;実装にちょっと珍しい多次元配列のエミュレート機能を使っています。&lt;code&gt;$passed{$m, $j}&lt;/code&gt;という部分です。
ぱっと見ハッシュ・スライスのようですが、シジルが$なことから分かるようにスカラ値を返します。&lt;/p&gt;

&lt;p&gt;これは次のように解釈されます：&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;$passed{ join($;, $m, $j) }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perl 5のハッシュが文字列しかキーにできないという制約からこのような形になっているのでしょう。&lt;code&gt;$;&lt;/code&gt;（&lt;code&gt;use English&lt;/code&gt;すると&lt;code&gt;$SUBSEP&lt;/code&gt;）は特殊変数で、デフォルトでは&lt;code&gt;"¥034"&lt;/code&gt;が入っています。これはUS-ASCIIではFS(File Separator)という制御文字なので、キーの値と混同されることはまずありません。&lt;/p&gt;

&lt;p&gt;Pythonなどのタプルをキーとする方法に比べると美しくありませんが、使い勝手に差はないので案外と重宝します。疎な多次元配列を作るときなどは配列リファレンスよりこちらの方がいいでしょう。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-7605045054256557102?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/7605045054256557102/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/05/project-euler-problem-29.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7605045054256557102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7605045054256557102'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/05/project-euler-problem-29.html' title='Project Euler - Problem 29'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5548462980610431039</id><published>2009-04-20T22:31:00.000+09:00</published><updated>2009-04-20T22:32:38.111+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 28</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;p&gt;再開言っておきながら10日も開いてしまいました。今度こそ再開します。きっと。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=28"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the sum of both diagonals in a 1001 by 1001 spiral formed in the same way?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2028"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;1001・1001の螺旋を同じ方法で生成したとき, 対角線上の数字の合計はいくつだろうか?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;1周する毎に数字の間隔が2広がるわけですから、単純に書いて十分早く答えが出ます。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;

my $sum = 1;
for (my ($i, $step) = (1, 2); $i &amp;lt; 1001 * 1001; $step += 2) {
  $sum += $i += $step for 1 .. 4;
}

say $sum;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5548462980610431039?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5548462980610431039/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-28.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5548462980610431039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5548462980610431039'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-28.html' title='Project Euler - Problem 28'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-666385381365232424</id><published>2009-04-10T23:42:00.007+09:00</published><updated>2009-04-20T22:27:56.277+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 27</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;p&gt;しばらく止まってましたが今日から再開。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=27"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Considering quadratics of the form:&lt;/p&gt;

&lt;p&gt;n&lt;sup&gt;2&lt;/sup&gt; + an + b, where |a| &amp;lt; 1000 and |b| &amp;lt; 1000&lt;/p&gt;

&lt;p&gt;Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2027"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;|a| &amp;lt; 1000, |b| &amp;lt; 1000 として以下の二次式を考える (ここで|a|は絶対値):&lt;/p&gt;

&lt;p&gt;n&lt;sup&gt;2&lt;/sup&gt; + an + b&lt;/p&gt;

&lt;p&gt;n=0から始めて連続する整数で素数を生成したときに最長の長さとなる上の二次式の, 係数a, bの積を答えよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;最大探索範囲は-999 &amp;lt;= a &amp;lt;= 999、-999 &amp;lt;= b &amp;lt;= 999なので、およそ4,000,000通りの係数の組合せを試すことになります。組合せ毎に数列を生成して、それが素数か判定するわけですからたまりません。簡単な検討を加えて範囲を絞りましょう。&lt;/p&gt;

&lt;p&gt;与えられた二次式をf(n)とおくと、f(0) = b、f(1) = a + b + 1です。
f(n)が長さ2以上の素数列を生成するならこれらは素数ですから、次のことがいえます：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;bは素数である&lt;/li&gt;
&lt;li&gt;a + b + 1は素数である&lt;/li&gt;
&lt;li&gt;b = 2のとき、aは偶数である&lt;/li&gt;
&lt;li&gt;それ以外のとき、aは奇数である&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;素数判定関数&lt;code&gt;is_prime&lt;/code&gt;には同じ引数が与えられることがよくあるのでメモ化しています。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;

sub prime_seq_len($$) {
  my ($coeff_a, $coeff_b) = @_;
  my $len = 0;
  my $n = 0;
  $len++, $n++ while is_prime($n * ($n + $coeff_a) + $coeff_b);
  return $len;
}

{
  my %primes = ( 2 =&amp;gt; 1 );
  sub is_prime(_) {
    my $n = abs shift;

    unless (exists $primes{$n}) {
      return 0 if $n &amp;lt; 2 or $n % 2 == 0;

      my $is_prime = 1;
      for (my $i = 3; $i &amp;lt;= sqrt $n; $i += 2) {
        if ($n % $i == 0) {
          $is_prime = 0;
          last;
        }
      }
      $primes{$n} = $is_prime;
    }

    return $primes{$n};
  }
}

my $longest = 0;
my $product;
for my $coeff_b (grep { is_prime } -999 .. 999) {
  my $modulo = $coeff_b == 2 ? 0 : 1;
  my @a_cands = grep { $_ % 2 == $modulo
                         and is_prime($_ + $coeff_b + 1) } -999 .. 999;
  for my $coeff_a (@a_cands) {
    my $len = prime_seq_len($coeff_a, $coeff_b);
    if ($longest &amp;lt; $len) {
      $longest = $len;
      $product = $coeff_a * $coeff_b;
    }
  }
}

say $product;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;追記&lt;/h3&gt;

&lt;p&gt;コメントで匿名氏に御指摘いただきました。&lt;/p&gt;

&lt;p&gt;b = n = 2とするとf(2) = 2&lt;sup&gt;2&lt;/sup&gt; + 2a + 2となり、これは明らかに（2より大きい）偶数です。
つまりb = 2のとき、生成する素数列の長さは高々2であり、無視できることになります。&lt;/p&gt;

&lt;p&gt;前掲のコードでb = 2のケースを考慮している部分（&lt;code&gt;$modulo&lt;/code&gt;のあたり）は不要になりました：&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;my $longest = 0;
my $product;
for my $coeff_b (grep { is_prime } -999 .. 999) {
  my @a_cands = grep { $_ % 2 != 0
                         and is_prime($_ + $coeff_b + 1) } -999 .. 999;
  for my $coeff_a (@a_cands) {
    my $len = prime_seq_len($coeff_a, $coeff_b);
    if ($longest &amp;lt; $len) {
      $longest = $len;
      $product = $coeff_a * $coeff_b;
    }
  }
}

say $product;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-666385381365232424?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/666385381365232424/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-27.html#comment-form' title='2 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/666385381365232424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/666385381365232424'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-27.html' title='Project Euler - Problem 27'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-8921004549690821676</id><published>2009-04-05T23:43:00.002+09:00</published><updated>2009-04-05T23:44:13.384+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 26</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=26"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the value of d &amp;lt; 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2026"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;d &amp;lt; 1000 なる 1/d の中で循環節が最も長くなるような d を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;筆算の過程から類推できるように、この問題は同じ余りが出るまでの間隔を調べる問題に置き替えることができます。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/reduce/;

sub rec_cycle_period($$) {
  my ($deno, $upper_lim) = @_;
  my %appeared_rems;
  my $remainder = 10;
  my $i = 0;
  do {
    return 0 if $remainder == 0;
    return -1 if $i &amp;gt;= $upper_lim;
    $appeared_rems{$remainder} = $i++;
    $remainder %= $deno;
    $remainder *= 10;
  } until exists $appeared_rems{$remainder};
  return $i - $appeared_rems{$remainder};
}

say
  map { $_-&amp;gt;[0] }
  reduce { $a-&amp;gt;[1] &amp;gt; $b-&amp;gt;[1] ? $a : $b }
  map { [$_, rec_cycle_period($_, 1000)] } 1 .. 1000;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-8921004549690821676?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/8921004549690821676/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-26.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8921004549690821676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8921004549690821676'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-26.html' title='Project Euler - Problem 26'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-2072743215882223688</id><published>2009-04-03T20:28:00.000+09:00</published><updated>2009-04-03T20:29:36.426+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 25</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=25"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the first term in the Fibonacci sequence to contain 1000 digits?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2025"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;1000桁になる最初の項の番号を答えよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;Gaucheのストリームライブラリを使ってみました。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use util.stream)

(define fibonacci-sequence
  (iterator-&amp;gt;stream
   (lambda (yield end)
     (let loop ((a 1) (b 1))
       (yield a)
       (loop b (+ a b))))))

(define (digits n)
  (define (digits-1 m acc)
    (if (&amp;lt; n m) acc
        (digits-1 (* m 10) (+ acc 1))))
  (digits-1 1 0))

(define (solve)
  (+ 1 (stream-index (lambda (n) (= 1000 (digits n)))
                     fibonacci-sequence)))

(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-2072743215882223688?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/2072743215882223688/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-25.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2072743215882223688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/2072743215882223688'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-25.html' title='Project Euler - Problem 25'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-6839307027406835070</id><published>2009-04-03T13:07:00.004+09:00</published><updated>2009-04-03T18:56:50.257+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 24</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=24"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2024"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;0,1,2,3,4,5,6,7,8,9からなる順列を辞書式に並べたときの100万番目を答えよ&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;n (&gt; 0)桁目の数字が決まると残りの数字の順列は(n - 1)!通りですから、一般にn桁の順列の（0から数えて）m番目というとき、m = p&lt;sub&gt;n&lt;/sub&gt;(n - 1)! + p&lt;sub&gt;n-1&lt;/sub&gt;(n - 2)! + ... + p&lt;sub&gt;1&lt;/sub&gt;(0)! (0 &amp;lt;= p&lt;sub&gt;i&lt;/sub&gt; &amp;lt; i)と表すと、p&lt;sub&gt;n&lt;/sub&gt;, p&lt;sub&gt;n-1&lt;/sub&gt;, ..., p&lt;sub&gt;1&lt;/sub&gt;の値は一意に定まります。
よってn桁目の数字を決めるとき、その時点で使える数字を昇順に並べた中からp&lt;sub&gt;n&lt;/sub&gt;番目の数字を選ぶという操作をn = 1まで繰り返すことで解が得られます。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)

(define (factorial n) (apply * (iota n 1)))

(define (solve)
  (define (solve-1 n digits acc)
    (if (null? digits) (list-&amp;gt;string (map integer-&amp;gt;digit (reverse acc)))
        (let* ((fact (factorial (- (length digits) 1)))
               (mult (floor (/ n fact)))
               (digit (ref digits mult))
               (rest (remove (cut = digit &amp;lt;&amp;gt;) digits)))
          (solve-1 (- n (* fact mult)) rest (cons digit acc)))))
  (solve-1 (- 1000000 1) (iota 10) '()))

(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-6839307027406835070?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/6839307027406835070/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-24.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6839307027406835070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6839307027406835070'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-24.html' title='Project Euler - Problem 24'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5405922888897230967</id><published>2009-04-02T23:45:00.001+09:00</published><updated>2009-04-02T23:45:54.137+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 23</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=23"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2023"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;2つの過剰数の和で書き表せない正の整数の総和を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://outer-inside.blogspot.com/2009/03/project-euler-problem-21.html"&gt;Problem 21&lt;/a&gt;を解くときに使った&lt;code&gt;divisors&lt;/code&gt;を流用してブルートフォース。&lt;code&gt;small-sigma&lt;/code&gt;は&lt;a href="http://ja.wikipedia.org/wiki/%E7%B4%84%E6%95%B0%E9%96%A2%E6%95%B0"&gt;約数関数&lt;/a&gt;です。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)

(define (divisors n)
  (define (divisor? m) (zero? (reremainder n m)))
  (let loop ((i 1) (early '()) (later '()))
    (if (&amp;gt; (* i i) n) (append-reverse early later)
        (cond
         ((= (* i i) n) (loop (+ i 1) (cons i early) later))
         ((divisor? i) (loop (+ i 1) (cons i early) (cons (/ n i) later)))
         (else (loop (+ i 1) early later))))))

;;; divisor function
(define (small-sigma x n) (apply + (map (cut expt &amp;lt;&amp;gt; x) (divisors n))))

(define small-sigma1 (cut small-sigma 1 &amp;lt;&amp;gt;))

(define (abundant-number? n) (&amp;lt; (* 2 n) (small-sigma1 n)))

(define (get-sieve upper-limit)
  (define lookup-table (make-vector (+ upper-limit 1) #f))
  (define (sum-of-abundants? n) (ref lookup-table n))
  (define abundant-numbers (filter abundant-number? (iota upper-limit 1)))
  (unless (null? abundant-numbers)
          (let init-lookup-table ((i (car abundant-numbers))
                                  (rest (cdr abundant-numbers)))
            (let inner-loop ((j i) (rest-of-rest rest))
              (define sum (+ i j))
              (if (&amp;gt; sum upper-limit)
                  (unless (null? rest)
                          (init-lookup-table (car rest) (cdr rest)))
                  (begin
                    (set! (ref lookup-table sum) #t)
                    (unless (null? rest-of-rest)
                            (inner-loop (car rest-of-rest)
                                        (cdr rest-of-rest))))))))
  sum-of-abundants?)

(define (solve)
  (apply + (remove (get-sieve 28123) (iota 28123 1))))

(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5405922888897230967?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5405922888897230967/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-23.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5405922888897230967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5405922888897230967'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/04/project-euler-problem-23.html' title='Project Euler - Problem 23'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5965890466149337682</id><published>2009-03-31T23:27:00.004+09:00</published><updated>2009-03-31T23:44:22.295+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 22</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=22"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the total of all the name scores in the file?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2022"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ファイル中の全名前のスコアの合計を求めよ.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;まさにPerlにうってつけの問題です。どこらへんに数学が必要なのかよく分かりません。&lt;/p&gt;

&lt;p&gt;ファイルの中身はダブルクォートで囲まれた名前のカンマ区切りリストです。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/sum/;

open my $input, 'names.txt' or die $!;
my @names = sort map { /([A-Z]+)/; $1 } split /,/, do { local $/; &amp;lt;$input&amp;gt; };
my $line_no = 1;
my $total_score = 0;
my $ord_A = ord 'A';
for my $name (@names) {
  $total_score
    += $line_no++ * sum map { ord($_) - $ord_A + 1 } split //, $name;
}
say $total_score;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5965890466149337682?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5965890466149337682/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-22.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5965890466149337682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5965890466149337682'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-22.html' title='Project Euler - Problem 22'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-8646133049861939993</id><published>2009-03-29T23:56:00.002+09:00</published><updated>2009-03-29T23:56:52.959+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 21</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=21"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Evaluate the sum of all the amicable numbers under 10000.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2021"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;10000未満の友愛数の合計を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;ほとんど書き下しただけです。注意点は&lt;a href="http://ja.wikipedia.org/wiki/%E5%AE%8C%E5%85%A8%E6%95%B0"&gt;完全数&lt;/a&gt;を計算に含めないことくらいでしょうか。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)

(define (divisors n)
  (define (divisor? m) (zero? (remainder n m)))
  (let loop ((i 2) (early '()) (later '()))
    (if (&amp;gt; (* i i) n) (cons 1 (append-reverse early later))
        (cond
         ((= (* i i) n) (loop (+ i 1) (cons i early) later))
         ((divisor? i) (loop (+ i 1) (cons i early) (cons (/ n i) later)))
         (else (loop (+ i 1) early later))))))

(define (d n) (apply + (divisors n)))

(define (amicable-number? n)
  (define m (d n))
  (and (not (= n m)) (= n (d m))))

(define (solve)
  (apply + (filter amicable-number? (iota (- 10000 1) 1))))

(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-8646133049861939993?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/8646133049861939993/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-21.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8646133049861939993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8646133049861939993'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-21.html' title='Project Euler - Problem 21'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-450012157836515901</id><published>2009-03-29T23:19:00.003+09:00</published><updated>2009-03-30T13:28:57.424+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 20</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=20"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of the digits in the number 100!&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2020"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;100! の各桁の数字の合計を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;毎度のことですがMath::BigIntのお世話になりました。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/sum reduce/;
use Math::BigInt;

sub factorial(_) {
  no warnings qw/once/;
  my $n = shift;
  return 1 if $n == 0;
  reduce { Math::BigInt-&amp;gt;new($a) * Math::BigInt-&amp;gt;new($b) } 1 .. $n;
}

say sum split //, factorial(Math::BigInt-&amp;gt;new(100));
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-450012157836515901?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/450012157836515901/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-20.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/450012157836515901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/450012157836515901'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-20.html' title='Project Euler - Problem 20'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-976735414855512963</id><published>2009-03-28T23:45:00.000+09:00</published><updated>2009-03-28T23:46:27.310+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 19</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=19"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2019"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;20世紀（1901年1月1日から2000年12月31日）で月の初めの日曜日の数を数えよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;単純な2重ループで足し合わせていくだけです。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)

(define (leap-year? year)
  (cond
   ((and (zero? (remainder year 100)) (not (zero? (remainder year 400)))) #f)
   ((zero? (remainder year 4)) #t)
   (else #f)))

(define (days-of year month)
  (case month
    ((1 3 5 7 8 10 12) 31)
    ((4 6 9 11) 30)
    ((2) (if (leap-year? year) 29 28))))

(define (day-of-week-after wday days)
  (define offset
    (case wday
      ((Sun) 0)
      ((Mon) 1)
      ((Tue) 2)
      ((Wed) 3)
      ((Thu) 4)
      ((Fri) 5)
      ((Sat) 6)))
  (list-ref '(Sun Mon Tue Wed Thu Fri Sat)
            (remainder (+ offset days) 7)))

(define (solve)
  (define wday-of-1-Jan-1901
    (day-of-week-after 'Mon
                       (apply + (map (cut days-of 1900 &amp;lt;&amp;gt;)
                                     (iota 12 1)))))
  (let yearly-loop ((sundays 0)
                    (wday wday-of-1-Jan-1901)
                    (year 1901))
    (if (&amp;gt; year 2000) sundays
        (receive (sundays-of-this-year first-wday-of-next-year)
                 (let monthly-loop ((sundays 0)
                                    (wday wday)
                                    (month 1))
                   (if (&amp;gt; month 12) (values sundays wday)
                       (monthly-loop
                        (if (eq? wday 'Sun) (+ sundays 1) sundays)
                        (day-of-week-after wday (days-of year month))
                        (+ month 1))))
                 (yearly-loop (+ sundays sundays-of-this-year)
                              first-wday-of-next-year
                              (+ year 1))))))

(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-976735414855512963?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/976735414855512963/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-19.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/976735414855512963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/976735414855512963'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-19.html' title='Project Euler - Problem 19'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-7596214628876984362</id><published>2009-03-28T22:27:00.001+09:00</published><updated>2009-03-28T23:11:51.233+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 18</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=18"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the maximum total from top to bottom of the triangle&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2018"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;三角形を頂点から下まで移動するとき、その最大の合計値を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/%E5%8B%95%E7%9A%84%E8%A8%88%E7%94%BB%E6%B3%95"&gt;動的計画法&lt;/a&gt;を使ってボトムアップで簡単に解くことができる問題です。&lt;/p&gt;

&lt;p&gt;簡単のため、小さい三角形で考えることにします：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0:    j
1:   h i
2:  e f g
3: a b c d
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;2行目の各点を頂点として、2行の小さい三角形が作れることが分かります。
上の例で言えば、(e, a, b)と(f, b, c)、(g, c, d)の3つです。
(e, a, b)の頂点eから末端（a、b、c、dのいずれか）に移動したとき、その数値の合計は最大でe + max(a, b)となります（maxは最大値を選ぶ関数）。同様に他の2つもf + max(b, c)、g + max(c, d)と表せます。
これらをE、F、Gとおくことにして、例を次のように書き換えます：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0:   j
1:  h i
2: E F G
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(h, E, F)からなる三角形の最大値はH = h + max(E, F)、(i, F, G)からなる三角形のそれはI = i + max(F, G)です。
Eは「頂点eから末端に至る経路の最大値」で、FやGも同様ですから、HとIは「頂点h（やi）から末端に至る経路の最大値」となります。&lt;/p&gt;

&lt;p&gt;これを先ほどと同様に置き換えて：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0:  j
1: H I
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;頂点jから末端に至る経路の最大値はJ = j + max(H, I)となり、これが解です。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/max/;

my @rows = map { [ split /\s+/ ] } &amp;lt;DATA&amp;gt;;
until (@rows == 1) {
  my $curr_row = $rows[-2];
  my $bigger_branch;
  for (my $i = 0; $i &amp;lt; @$curr_row; $i++) {
    $bigger_branch = max $rows[-1][$i], $rows[-1][$i + 1];
    $curr_row-&amp;gt;[$i] += $bigger_branch;
  }
  $#rows--;
}

say $rows[0][0];

__END__
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-7596214628876984362?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/7596214628876984362/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-18.html#comment-form' title='3 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7596214628876984362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7596214628876984362'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-18.html' title='Project Euler - Problem 18'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5144228389354773967</id><published>2009-03-25T22:46:00.001+09:00</published><updated>2009-03-26T16:46:14.549+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 17</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=17"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used? &lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2017"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;1 から 1000 (one thousand) までの数字をすべて英単語で書けば、全部で何文字になるか。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;どう考えても数値計算じゃなくて文字列処理の問題です。つまりPerlの出番です。
数値を英語表現に変換する必要がありますが、&lt;a href="http://search.cpan.org/search?query=Lingua%3A%3AEN%3A%3ANumbers&amp;amp;mode=all"&gt;Lingua::EN::Numbers&lt;/a&gt;というCPANモジュールがまさにその機能を持っています。&lt;/p&gt;

&lt;p&gt;以前のバージョンではイギリス/アメリカ英語の切り替え機能を持っていたようですが、現在は削除されています。生成される英語表現はイギリス英語が元になっているようなので、当座の用は満たせます。&lt;/p&gt;

&lt;p&gt;コードの本質的な箇所ではありませんが、Perl 5.10から関数プロトタイプに&lt;code&gt;_&lt;/code&gt;を指定できるようになりました。
これを使うと、引数が省略されたとき&lt;code&gt;$_&lt;/code&gt;の値を使うという組み込み関数と同様の挙動を簡単に実現できます。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use Lingua::EN::Numbers qw/num2en/;
use List::Util qw/sum/;

sub num_of_chars_in_english(_) {
  my $english_expr = num2en shift;
  $english_expr =~ tr/a-z//;
}

say sum map { num_of_chars_in_english } 1 .. 1000;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5144228389354773967?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5144228389354773967/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-17.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5144228389354773967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5144228389354773967'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-17.html' title='Project Euler - Problem 17'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-6327944668925114092</id><published>2009-03-25T19:26:00.002+09:00</published><updated>2009-03-25T19:26:58.877+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 16</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=16"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the sum of the digits of the number 2^(1000)?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2016"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;2&lt;sup&gt;1000&lt;/sup&gt; の各数字の合計を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;Gaucheの整数精度は無制限（実はR5RSでは要求されていない。驚き）なので特に悩む必要はありません。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(define (solve)
  (apply + (map digit-&amp;gt;integer (string-&amp;gt;list (number-&amp;gt;string (expt 2 1000))))))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ついでにPerl 5.10の一行野郎。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;perl -Mbigint -MList::Util=sum -E"say sum split //, 2 ** 1000"
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-6327944668925114092?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/6327944668925114092/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-16.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6327944668925114092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/6327944668925114092'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-16.html' title='Project Euler - Problem 16'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-1597046699892803557</id><published>2009-03-24T23:43:00.003+09:00</published><updated>2009-03-25T00:22:36.482+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 15</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=15"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How many routes are there through a 20・20 grid?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2015"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;20 ・ 20 のマス目ではいくつのルートがあるか。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;グリッド上の座標を(x, y)で表すこととし、左上の始点を(0, 0)、右下の終点を(20, 20)と定めます。
座標(x, y)から(20, 20)へのルート数をroutesFrom(x, y)と書くことにすると、この問題はroutesFrom(0, 0)を求める問題に相当します。
routesFrom(x, y)は次のようにして求められます：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;routesFrom(x, y) = 1 (x = 20, y = 20)&lt;/li&gt;
&lt;li&gt;routesFrom(x, y) = 0 (x &gt; 20 or y &gt; 20)&lt;/li&gt;
&lt;li&gt;routesFrom(x, y) = routesFrom(x + 1, y) + routesFrom(x, y + 1) (otherwise)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;routesFrom(0, 0)の計算量はグリッドの大きさnの増加に対応して急激に大きくなります（多分計算量の上限はO(2^n)くらい）。
routesFrom(0, 0) = routesFrom(1, 0) + routesFrom(0, 1) = routesFrom(2, 0) + routesFrom(1, 1) + routesFrom(1, 1) + routesFrom(0, 2) = ...といったように、基底ケース（上の1.と2.）に行き当たるまで倍々に項が増えていきます。今回はn=20なので、このままでは現実的な時間内に終わりません。&lt;/p&gt;

&lt;p&gt;別々のルートが同じ座標を通ることはよくあります。先ほどの展開でroutesFrom(1, 1)という項が2回出てきているのは、(0, 0)から(1, 1)に至るルートが2つ存在するからです。
その座標に至るまでのルートに関わらずそれ以降に取り得るルートの数は同じなので、routesFrom(x, y)の値をメモ化することで膨大な計算を省くことができます。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)
(define (count-routes num-cells)
  (define lookup-table (make-vector (+ num-cells 1)))
  (define (routes-from x y) (ref (ref lookup-table y) x))
  (define (count-routes-1 x y)
    (cond
     ((or (&amp;gt; x num-cells) (&amp;gt; y num-cells)) 0)
     ((and (= x num-cells) (= y num-cells)) 1)
     ((not (zero? (routes-from x y))) (routes-from x y))
     (else
      (let ((num-routes (+ (count-routes-1 (+ x 1) y)
                           (count-routes-1 x (+ y 1)))))
        (set! (routes-from x y) num-routes)
        num-routes))))
  (set! (setter routes-from)
        (lambda (x y num-routes) (set! (ref (ref lookup-table y) x) num-routes)))
  (for-each (lambda (i)
              (set! (ref lookup-table i) (make-vector (+ num-cells 1) 0)))
            (iota (+ num-cells 1)))
  (count-routes-1 0 0))
(define (solve) (count-routes 20))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-1597046699892803557?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/1597046699892803557/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-15.html#comment-form' title='2 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1597046699892803557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1597046699892803557'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-15.html' title='Project Euler - Problem 15'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-7677587275435935440</id><published>2009-03-23T21:37:00.002+09:00</published><updated>2009-03-24T23:51:43.128+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 14</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;p&gt;ある関数を繰り返し適用して得られる数列が最も長くなる初期値n（1,000,000未満）を求める問題です。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=14"&gt;原文&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2014"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;nから始まる数列の長さをlen(n)で表すと、次のように定義できます：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;len(n) = 1 (n = 1)&lt;/li&gt;
&lt;li&gt;len(n) = len(3n + 1) + 1 (nは奇数)&lt;/li&gt;
&lt;li&gt;len(n) = len(n / 2)  + 1 (nは偶数)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;つまり、len(n)の計算は1.の場合を基底ケースとする再帰アルゴリズムとして実装できます。&lt;/p&gt;

&lt;p&gt;これをそのまま実装しても答えが得られますが、非常に遅いです。高速化の為に少し検討を加えましょう。&lt;/p&gt;

&lt;p&gt;まず56から始まる数列を考えます。56は偶数なので3.の場合に該当し、len(56) = len(56 / 2) + 1 = len(28) + 1です。また、9から始まる数列の場合は2.に該当し、len(9) = len(3 * 9 + 1) + 1 = len(28) + 1となります。
つまりlen(56) = len(9) = len(28) + 1というわけで、len(56)とlen(9)の値は実は同じです。2.と3.の再帰式を見て予想できるように、このような重複は度々起こるので、それぞれの計算でlen(28)の計算をやり直すようなことをしていると大きな無駄となります。&lt;/p&gt;

&lt;p&gt;これを解決するには過去に計算したlen(n)の値を覚えておき、次に同じnが与えられた時には覚えていた値を返すようにします。そうすることで2度目以降の関数呼び出しでは計算を省くことができ、時間の節約になります。これは同じ引数に対して常に同じ値を返す（つまり参照透過性がある）関数一般に使えるテクニックで、これを&lt;a href="http://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E5%8C%96"&gt;メモ化&lt;/a&gt;と呼びます。&lt;/p&gt;

&lt;p&gt;そう言うわけで長々と説明しましたが、要は&lt;a href="http://outer-inside.blogspot.com/2009/03/project-euler-problem-10.html"&gt;Problem 10&lt;/a&gt;で使ったルックアップ・テーブルと同じものです。今回はクロージャ生成時に確保されたベクタの長さより大きい&lt;code&gt;n&lt;/code&gt;が与えられる場合（十分大きい奇数が与えられた時）が有り得るので、上限（&lt;code&gt;upper-limit&lt;/code&gt;）より大きい&lt;code&gt;n&lt;/code&gt;に対してはその都度計算し直しています。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)
(define (get-sequence-length next-value upper-limit)
  (define lookup-table (make-vector (+ upper-limit 1) 0))
  (define (sequence-length n)
    (let ((len (if (&amp;gt; n upper-limit) 0 (ref lookup-table n))))
      (if (not (zero? len)) len
          (let ((len
                 (+ 1 (sequence-length (next-value n)))))
            (unless (&amp;gt; n upper-limit) (set! (sequence-length n) len))
            len))))
  (set! (setter sequence-length)
        (lambda (n len) (set! (ref lookup-table n) len)))
  (set! (sequence-length 1) 1)
  sequence-length)
(define (solve)
  (define sequence-length
    (get-sequence-length (lambda (n) (if (even? n) (/ n 2) (+ (* 3 n) 1)))
                         999999))
  (car (fold (lambda (a b) (if (&amp;gt; (cdr a) (cdr b)) a b))
             '(0 . 0)
             (map (lambda (n) (cons n (sequence-length n))) (iota 999999 1)))))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-7677587275435935440?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/7677587275435935440/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-14.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7677587275435935440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7677587275435935440'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-14.html' title='Project Euler - Problem 14'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5889170365180971973</id><published>2009-03-23T02:19:00.002+09:00</published><updated>2009-03-24T23:51:08.346+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 13</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=13"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Work out the first ten digits of the sum of the following one-hundred 50-digit numbers.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2013"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;以下の50桁の数字100個の総和の上位10桁を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use Math::BigInt;

my $result = Math::BigInt-&amp;gt;new(0);
$result += $_ for &amp;lt;DATA&amp;gt;;
say substr($result, 0, 10);

__DATA__
37107287533902102798797998220837590246510135740250
46376937677490009712648124896970078050417018260538
74324986199524741059474233309513058123726617309629
91942213363574161572522430563301811072406154908250
23067588207539346171171980310421047513778063246676
89261670696623633820136378418383684178734361726757
28112879812849979408065481931592621691275889832738
44274228917432520321923589422876796487670272189318
47451445736001306439091167216856844588711603153276
70386486105843025439939619828917593665686757934951
62176457141856560629502157223196586755079324193331
64906352462741904929101432445813822663347944758178
92575867718337217661963751590579239728245598838407
58203565325359399008402633568948830189458628227828
80181199384826282014278194139940567587151170094390
35398664372827112653829987240784473053190104293586
86515506006295864861532075273371959191420517255829
71693888707715466499115593487603532921714970056938
54370070576826684624621495650076471787294438377604
53282654108756828443191190634694037855217779295145
36123272525000296071075082563815656710885258350721
45876576172410976447339110607218265236877223636045
17423706905851860660448207621209813287860733969412
81142660418086830619328460811191061556940512689692
51934325451728388641918047049293215058642563049483
62467221648435076201727918039944693004732956340691
15732444386908125794514089057706229429197107928209
55037687525678773091862540744969844508330393682126
18336384825330154686196124348767681297534375946515
80386287592878490201521685554828717201219257766954
78182833757993103614740356856449095527097864797581
16726320100436897842553539920931837441497806860984
48403098129077791799088218795327364475675590848030
87086987551392711854517078544161852424320693150332
59959406895756536782107074926966537676326235447210
69793950679652694742597709739166693763042633987085
41052684708299085211399427365734116182760315001271
65378607361501080857009149939512557028198746004375
35829035317434717326932123578154982629742552737307
94953759765105305946966067683156574377167401875275
88902802571733229619176668713819931811048770190271
25267680276078003013678680992525463401061632866526
36270218540497705585629946580636237993140746255962
24074486908231174977792365466257246923322810917141
91430288197103288597806669760892938638285025333403
34413065578016127815921815005561868836468420090470
23053081172816430487623791969842487255036638784583
11487696932154902810424020138335124462181441773470
63783299490636259666498587618221225225512486764533
67720186971698544312419572409913959008952310058822
95548255300263520781532296796249481641953868218774
76085327132285723110424803456124867697064507995236
37774242535411291684276865538926205024910326572967
23701913275725675285653248258265463092207058596522
29798860272258331913126375147341994889534765745501
18495701454879288984856827726077713721403798879715
38298203783031473527721580348144513491373226651381
34829543829199918180278916522431027392251122869539
40957953066405232632538044100059654939159879593635
29746152185502371307642255121183693803580388584903
41698116222072977186158236678424689157993532961922
62467957194401269043877107275048102390895523597457
23189706772547915061505504953922979530901129967519
86188088225875314529584099251203829009407770775672
11306739708304724483816533873502340845647058077308
82959174767140363198008187129011875491310547126581
97623331044818386269515456334926366572897563400500
42846280183517070527831839425882145521227251250327
55121603546981200581762165212827652751691296897789
32238195734329339946437501907836945765883352399886
75506164965184775180738168837861091527357929701337
62177842752192623401942399639168044983993173312731
32924185707147349566916674687634660915035914677504
99518671430235219628894890102423325116913619626622
73267460800591547471830798392868535206946944540724
76841822524674417161514036427982273348055556214818
97142617910342598647204516893989422179826088076852
87783646182799346313767754307809363333018982642090
10848802521674670883215120185883543223812876952786
71329612474782464538636993009049310363619763878039
62184073572399794223406235393808339651327408011116
66627891981488087797941876876144230030984490851411
60661826293682836764744779239180335110989069790714
85786944089552990653640447425576083659976645795096
66024396409905389607120198219976047599490197230297
64913982680032973156037120041377903785566085089252
16730939319872750275468906903707539413042652315011
94809377245048795150954100921645863754710598436791
78639167021187492431995700641917969777599028300699
15368713711936614952811305876380278410754449733078
40789923115535562561142322423255033685442488917353
44889911501440648020369068063960672322193204149535
41503128880339536053299340368006977710650566631954
81234880673210146739058568557934581403627822703280
82616570773948327592232845941706525094512325230608
22918802058777319719839450180888072429661980811197
77158542502016545090413245809786882778948721859617
72107838435069186155435662884062257473692284509516
20849603980134001723930671666823555245252804609722
53503534226472524250874054075591789781264330331690
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;...すいません、手抜きです。でもこういうのは軽量言語の役得じゃないですかね。Cだって別に&lt;a href="http://gmplib.org/"&gt;GMP&lt;/a&gt;使ってもいいわけだし。
「まっとうな」やり方だと10桁程度ずつに区切って、それぞれを合算した上で桁上がり分を上の桁に加えるような手順で計算できるはずです。やらないけど。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5889170365180971973?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5889170365180971973/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-13.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5889170365180971973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5889170365180971973'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-13.html' title='Project Euler - Problem 13'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3578071798442960848</id><published>2009-03-23T01:37:00.004+09:00</published><updated>2009-03-24T23:50:09.061+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 12</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=12"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the value of the first triangle number to have over five hundred divisors?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2012"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;501 個以上の約数をもつ最初の三角数はいくらか。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;約数の個数は素因数分解の結果から求めることができます。
例えばn = p&lt;sup&gt;a&lt;/sup&gt; * q&lt;sup&gt;b&lt;/sup&gt;（pとqは素数）という合成数がある場合、約数は以下の表のようになります：&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;p&lt;/td&gt;&lt;td&gt;p&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;td rowspan="5"&gt;...&lt;/td&gt;&lt;td&gt;p&lt;sup&gt;a&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;q&lt;/td&gt;&lt;td&gt;p * q&lt;/td&gt;&lt;td&gt;p&lt;sup&gt;2&lt;/sup&gt; * q&lt;/td&gt;&lt;td&gt;p&lt;sup&gt;a&lt;/sup&gt; * q&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;q&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;p * q&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;p&lt;sup&gt;2&lt;/sup&gt; * q&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;p&lt;sup&gt;a&lt;/sup&gt; * q&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan="5"&gt;...&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;q&lt;sup&gt;b&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;p * q&lt;sup&gt;b&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;p&lt;sup&gt;2&lt;/sup&gt; * q&lt;sup&gt;b&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;p&lt;sup&gt;a&lt;/sup&gt; * q&lt;sup&gt;b&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;p&lt;sup&gt;0&lt;/sup&gt; = q&lt;sup&gt;0&lt;/sup&gt; = 1であることを考えれば、0..aの(a + 1)通りのpのべき乗と、0..bの(b + 1)通りのqのべき乗を掛け合わせた数がnの約数であることが分かります。
これは素因数が3つ以上の場合も同様で、一般にp&lt;sup&gt;a&lt;/sup&gt; * q&lt;sup&gt;b&lt;/sup&gt; * r&lt;sup&gt;c&lt;/sup&gt; * ...の約数は(a + 1)(b + 1)(c + 1)...個存在します。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://outer-inside.blogspot.com/2009/03/project-euler-problem-3.html"&gt;Problem 3&lt;/a&gt;で使った素因数分解を行う関数&lt;code&gt;factorize&lt;/code&gt;を改良し、各素因数について、べき乗回数をcdrに入れたペアのリストを返すようにしました。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(define (triangle-number n) (* (+ 1 n) (/ n 2)))
(define (factorize n)
  (define max-divisor (floor-&amp;gt;exact (sqrt n)))
  (define (factorize-1 n div result)
    (if (&amp;gt; div max-divisor)
        (if (= n 1) result (cons (cons n 1) result))
        (let count ((n n) (i 0))
          (define (divisor? m) (zero? (modulo n m)))
          (if (divisor? div) (count (/ n div) (+ i 1))
              (factorize-1 n (+ div 2)
                           (if (zero? i) result
                               (cons (cons div i) result)))))))
  (let prepare ((n n) (i 0))
    (if (even? n) (prepare (/ n 2) (+ i 1))
        (factorize-1 n 3 (if (zero? i) '() (cons (cons 2 i) '()))))))
(define (num-of-divisors-of n)
  (apply * (map (lambda (factor) (+ (cdr factor) 1)) (factorize n))))
(define (solve)
  (let loop ((i 1))
    (define tri (triangle-number i))
    (if (&amp;gt; (num-of-divisors-of tri) 500) tri
        (loop (+ i 1)))))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;参考文献&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mathschallenge.net/index.php?section=faq&amp;amp;ref=number/number_of_divisors"&gt;mathschallenge.net&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3578071798442960848?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3578071798442960848/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-12.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3578071798442960848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3578071798442960848'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-12.html' title='Project Euler - Problem 12'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-4216043795483650991</id><published>2009-03-22T22:03:00.001+09:00</published><updated>2009-03-24T23:49:12.149+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 11</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=11"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the greatest product of four adjacent numbers in any direction (up, down, left, right, or diagonally) in the 20・20 grid?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2011"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;上下左右斜めのいずれかの方向で連続する4つの数字の積のうち最大のものを求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;単なる総当り問題です。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/max reduce/;

my @grid = map { chomp; [ split /\s+/ ] } &amp;lt;DATA&amp;gt;;
my @products;
OUTER:
for (my $i = 0; $i &amp;lt; @grid; $i++) {
  my $curr_row = $grid[$i];
  for (my $j = 0; $j &amp;lt; @$curr_row; $j++) {
    last OUTER if $i &amp;gt;= @grid - 3 and $j &amp;gt;= @$curr_row - 3;

    if ($j &amp;lt; @$curr_row - 3) {
      push @products, reduce { $a * $b } map { $grid[$i][$j + $_] } 0 .. 3;
    }
    if ($i &amp;lt; @grid - 3) {
      push @products, reduce { $a * $b } map { $grid[$i + $_][$j] } 0 .. 3;
    }
    if ($i &amp;lt; @grid - 3 and $j &amp;lt; @$curr_row - 3) {
      push @products,
        reduce { $a * $b } map { $grid[$i + $_][$j + $_] } 0 .. 3;
    }
    if ($i &amp;lt; @grid - 3 and $j &amp;gt;= 3) {
      push @products,
        reduce { $a * $b } map { $grid[$i + $_][$j - $_] } 0 .. 3;
    }
  }
}
say max @products;

__END__
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-4216043795483650991?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/4216043795483650991/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-11.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4216043795483650991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/4216043795483650991'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-11.html' title='Project Euler - Problem 11'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-1676157632626555308</id><published>2009-03-22T03:34:00.006+09:00</published><updated>2009-03-31T23:58:23.266+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 10</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=10"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of all the primes below two million.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%2010"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;200万以下の全ての素数の和を計算しなさい.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;素数を探す点はProblem 7と同様ですが、2,000,000以下の素数は148,933個も存在するので計算量は文字通り桁違いです。
アルゴリズムを替えるほどではありませんが、以前のコードは大きなリストを何度もコピーし、&lt;code&gt;filter&lt;/code&gt;にかけているので低速です。
ベクタを使ったルックアップ・テーブルを事前に用意し、&lt;code&gt;filter&lt;/code&gt;の適用も1回に抑えることで3倍程度高速化しました。2以外の偶数が素数でないのは明らかなので、奇数のみを篩にかけ、後から2と&lt;code&gt;cons&lt;/code&gt;しています。&lt;/p&gt;

&lt;p&gt;SRFI-17の&lt;code&gt;setter&lt;/code&gt;を使ってベクタの書き換えを抽象化しています。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;(use srfi-1)

(define (get-sieve upper-limit)
  (define lookup-table (make-vector (+ upper-limit 1) #t))
  (define (prime? n) (ref lookup-table n))
  (set! (setter prime?) (lambda (n retval) (set! (ref lookup-table n) retval)))
  (set! (prime? 0) #f)
  (set! (prime? 1) #f)
  (let sieve-evens ((i 4))
    (unless (&amp;gt; i upper-limit)
            (set! (prime? i) #f)
            (sieve-evens (+ i 2))))
  (let sieve-odds ((i 3))
    (unless (&amp;gt; (* i i) upper-limit)
            (when (prime? i)
                  (let inner-loop ((j (* i i)))
                    (unless (&amp;gt; j upper-limit)
                            (set! (prime? j) #f)
                            (inner-loop (+ j (* i 2))))))
            (sieve-odds (+ i 1))))
  prime?)

(define (solve)
  (define prime? (get-sieve 2000000))
  (apply + (cons 2 (filter prime? (iota (- 1000000 1) 3 2)))))

(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-1676157632626555308?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/1676157632626555308/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-10.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1676157632626555308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/1676157632626555308'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-10.html' title='Project Euler - Problem 10'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-8972423485712703444</id><published>2009-03-21T22:24:00.001+09:00</published><updated>2009-03-22T03:41:14.793+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 9</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=9"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There exists exactly one Pythagorean triplet for which a + b + c = 1000.
Find the product abc.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%209"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;a + b + c = 1000となるピタゴラスの三つ組が一つだけ存在する. このa,b,cの積を計算しなさい.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;何の変哲もない2重ループです。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(define (square n) (* n n))
(define (solve)
  (let outer-loop ((i 1))
    (let inner-loop ((j 1))
      (define k (sqrt (+ (square i) (square j))))
      (cond
       ((= (+ i j k) 1000) (* i j (inexact-&amp;gt;exact k)))
       ((&amp;gt; (+ i j k) 1000) (outer-loop (+ i 1)))
       (else               (inner-loop (+ j 1)))))))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-8972423485712703444?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/8972423485712703444/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-9.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8972423485712703444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8972423485712703444'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-9.html' title='Project Euler - Problem 9'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3183702967546388711</id><published>2009-03-20T19:37:00.006+09:00</published><updated>2009-03-22T03:40:54.179+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl5'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Project Euler - Problem 8</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=8"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the greatest product of five consecutive digits in the 1000-digit number.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%208"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;1000桁の数字から5つの連続する数字を取り出してその積を計算する。そのような積の中で最大のものの値はいくらか。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;計算よりデータの読み込みが面倒です。Perl 5を使って解くことにしました。
&lt;code&gt;do { local $/; &amp;lt;FILE_HANDLE&amp;gt; }&lt;/code&gt;はファイル一気読みのイディオムですが、改行文字を落とすために&lt;code&gt;grep&lt;/code&gt;をかけています。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use warnings;
use feature qw/say/;
use List::Util qw/reduce/;

my @digits = do { local $/; grep /\d/, split //, &amp;lt;DATA&amp;gt; };
my $max = 0;
until (5 &amp;gt; @digits) {
  no warnings qw/once/;
  my $product = reduce { $a * $b } @digits[0 .. 4];
  $max = $product if $max &amp;lt; $product;
  shift @digits;
}

say $max;

__DATA__
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3183702967546388711?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3183702967546388711/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-8.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3183702967546388711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3183702967546388711'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-8.html' title='Project Euler - Problem 8'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3180408016775154578</id><published>2009-03-20T14:06:00.005+09:00</published><updated>2009-03-20T18:01:53.242+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='currying'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Schemeでカリー化</title><content type='html'>&lt;p&gt;Haskellの有名な特徴として、関数が勝手に&lt;a href="http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96"&gt;カリー化&lt;/a&gt;されるという点があります。
要するにHaskellの関数は常に部分適用可能になっていて、&lt;code&gt;f foo bar baz&lt;/code&gt;という関数適用は&lt;code&gt;(((f foo) bar) baz)&lt;/code&gt;と解釈されています。これは非常に強力な機能で、汎用的な関数を目的に合わせて簡単に特殊化することができます。&lt;/p&gt;

&lt;p&gt;Schemeやその他のLispでは、引数は必ず同時に与えないといけないので、カリー化したものを作ろうとするとクロージャを使って&lt;code&gt;(define f (lambda (x) (lambda (y) (lambda (z) ...))))&lt;/code&gt;とでもしなければなりません。しかも呼び出すときには&lt;code&gt;(((f foo) bar) baz)&lt;/code&gt;と、1つずつ順番に適用する必要があります。
私が欲しいのは、"（Haskellが透過的にやっているように）与えられた引数を先頭から順に束縛し、足りない分を引数とするクロージャを返す"ような関数です。&lt;code&gt;((f foo) bar baz)&lt;/code&gt;だろうが&lt;code&gt;(f foo bar baz)&lt;/code&gt;だろうが&lt;code&gt;(((f foo) bar) baz)&lt;/code&gt;だろうが同じ結果を返す関数を作りたいわけです。そこで、カリー化関数を作成するマクロを書きました。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(define-syntax curry
  (syntax-rules ()
    ((_ (arg0) body ...) (lambda (arg0) body ...))
    ((_ (arg0 arg1 ...) body ...)
     (lambda (arg0 . rest)
       (define applied (curry (arg1 ...) body ...))
       (if (null? rest) applied
           (apply applied rest))))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;このマクロを使って作成した関数は、引数を先頭から束縛していき、すべての引数が揃ったときに値を返します。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(define greet (curry (when who)
                     (display
                          (string-append "good "
                                         when ", " who "."
                                         " how are you?"))
                     (newline)))
(greet "morning" "John")   ;;; prints "good morning, John. how are you?"
((greet "morning") "John") ;;; same as above
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;バグなどありましたらコメントで教えてください。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3180408016775154578?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3180408016775154578/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/scheme.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3180408016775154578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3180408016775154578'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/scheme.html' title='Schemeでカリー化'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-7237871091160393305</id><published>2009-03-20T02:04:00.003+09:00</published><updated>2009-03-22T03:40:35.010+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 7</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=7"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the 10001st prime number?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%207"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;10001 番目の素数を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;素数判定といえば&lt;a href="http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9"&gt;エラトステネスの篩&lt;/a&gt;という有名なアルゴリズムがあります。
それを実装したのが下記の&lt;code&gt;eratos&lt;/code&gt;で、与えられたリスト（昇順に並んでいると仮定）を篩にかけ、残った数値をリストにして返します。リストを先頭の要素と残りに分割するというのはHaskellやPerlなどでよく見かけるパターンですが、SchemeでもSRFI-1の&lt;code&gt;car+cdr&lt;/code&gt;を使って簡潔に書けます。
&lt;code&gt;take-primes&lt;/code&gt;は与えられた個数以上の素数が得られるまで、リストを拡張しながら&lt;code&gt;eratos&lt;/code&gt;を繰り返し適用し、得られたリストから与えられた個数の素数を返します。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)
(define (eratos xs)
  (define (eratos-1 xs result)
    (if (null? xs) (reverse result)
        (let ((last-num (last xs)))
          (receive (n ns) (car+cdr xs)
                   (if (&amp;lt; last-num (* n n)) (append (reverse result) xs)
                       (let ((not-multiple-of-n?
                              (lambda (m) (not (zero? (modulo m n))))))
                         (eratos-1 (filter not-multiple-of-n? ns)
                                   (cons n result))))))))
  (eratos-1 xs '()))
(define (take-primes num-primes)
  (define (take-primes-1 primes)
    (if (&amp;lt; num-primes (length primes)) (take primes num-primes)
        (take-primes-1 (eratos (append primes
                                       (iota num-primes
                                             (+ (last primes) 2)
                                             2))))))
  (take-primes-1 '(2 3)))
(define (solve)
  (last (take-primes 10001)))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-7237871091160393305?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/7237871091160393305/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-7.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7237871091160393305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/7237871091160393305'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-7.html' title='Project Euler - Problem 7'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-9121261733042711593</id><published>2009-03-19T16:51:00.002+09:00</published><updated>2009-03-22T03:40:18.320+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 6</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=6"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%206"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;最初の100個の自然数について和の二乗と二乗の和の差を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;これまた簡単な問題。ほとんど問題を書き下すだけの作業です。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)
(define (solve)
  (define nums (iota 100 1))
  (define sum-of-squares
    (apply + (map (lambda (n) (expt n 2)) nums)))
  (define square-of-sum
    (expt (apply + nums) 2))
  (- square-of-sum sum-of-squares))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-9121261733042711593?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/9121261733042711593/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-6.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/9121261733042711593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/9121261733042711593'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-6.html' title='Project Euler - Problem 6'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-678548333432767211</id><published>2009-03-19T14:42:00.007+09:00</published><updated>2009-03-25T19:15:49.479+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='perl6'/><title type='text'>Project Euler - Problem 5</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=5"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the smallest number that is evenly divisible by all of the numbers from 1 to 20?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%205"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;1 から 20 までの整数全てで割り切れる数字の中で最小の値はいくらになるか。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;いきなり難易度が下がりました。人はそれを最小公倍数と呼びます。
Schemeには組み込み関数&lt;code&gt;lcm&lt;/code&gt;があるので、何も面白くありません。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)
(define (solve)
  (apply lcm (iota 20 1)))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これでおしまい。せっかくなのでPerl 6版の&lt;code&gt;gcd&lt;/code&gt;/&lt;code&gt;lcm&lt;/code&gt;関数でも貼っておきます。&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&lt;code&gt;subset NonZeroInt of Int where { $_ != 0 }
sub gcd(NonZeroInt $m is copy, NonZeroInt $n is copy, NonZeroInt *@rest) {
  $m = -$m if $m &amp;lt; 0;
  $n = -$n if $n &amp;lt; 0;
  $m, $n = $n, $m if $m &amp;lt; $n;
  my Int $mod = $m % $n;
  my Int $gcd = $mod == 0 ?? $n !! gcd($n, $mod);
  +@rest == 0 ?? $gcd !! gcd($gcd, |@rest);
}
sub lcm(NonZeroInt $m is copy, NonZeroInt $n is copy, NonZeroInt *@rest) {
  $m = -$m if $m &amp;lt; 0;
  $n = -$n if $n &amp;lt; 0;
  my Int $lcm = $m * $n / gcd($m, $n);
  +@rest == 0 ?? $lcm !! lcm($lcm, |@rest);
}
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-678548333432767211?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/678548333432767211/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-5.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/678548333432767211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/678548333432767211'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-5.html' title='Project Euler - Problem 5'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-8505650326272941996</id><published>2009-03-19T13:49:00.004+09:00</published><updated>2009-03-22T03:39:48.487+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 4</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=4"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the largest palindrome made from the product of two 3-digit numbers.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%204"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;3桁の数の積で表される回文数のうち最大のものはいくらになるか。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;3桁の数値なので、考えられる項は100 .. 999です。つまりナイーブな実装では、900 * 900 = 810,000回の乗算を行う必要があります。これは不可能な大きさではありません。というより私がまともな解法を思いつかないので、今回はこれで。&lt;/p&gt;

&lt;p&gt;まず回文数かどうか判定する述語を作ります。&lt;code&gt;palindromic-number?&lt;/code&gt;という関数がそれです。やっていることは単純で、数値を文字列に変換した上で反転したものと比較しているだけです。文字列の反転はSRFI-13の&lt;code&gt;string-reverse&lt;/code&gt;で可能です。
実際には文字列の前半と、反転させた後半のみを比較すれば良いのですが、文字列を切り出すコストの方が高いのでそのまま比較しています。&lt;/p&gt;

&lt;p&gt;実際の探索を行っている&lt;code&gt;solve&lt;/code&gt;は単純で、すべての積を計算した上で、その中から回文数をSRFI-1の&lt;code&gt;filter&lt;/code&gt;で抽出してリスト&lt;code&gt;palins&lt;/code&gt;とし、そこから&lt;code&gt;max&lt;/code&gt;で最大値を選び出します。
簡単な最適化として、例えば100 * 101と101 * 100は同じなので、無駄な計算を省くために100 &amp;lt;= i &amp;lt;= j &amp;lt;= 999が常に成り立つように内側の&lt;code&gt;map&lt;/code&gt;に渡すリストを工夫しています。これによって乗算の回数をおよそ半分にできます。&lt;/p&gt;

&lt;p&gt;これまでの問題がミリ秒単位で計算できたのに比べると今回のプログラムは時間がかかりますが、数秒で計算できると思います。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)
(use srfi-13)
(define (palindromic-number? n)
  (define n-str (number-&amp;gt;string n))
  (string=? n-str (string-reverse n-str)))
(define (solve)
  (define palins
    (filter palindromic-number?
            (apply append
                   (map (lambda (i)
                          (map (lambda (j) (* i j)) (iota (- 1000 i) i)))
                        (iota 900 100)))))
  (apply max palins))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-8505650326272941996?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/8505650326272941996/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-4.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8505650326272941996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/8505650326272941996'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-4.html' title='Project Euler - Problem 4'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-5971514200397623451</id><published>2009-03-19T02:00:00.008+09:00</published><updated>2009-03-22T03:39:31.902+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 3</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=3"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What is the largest prime factor of the number 600851475143 ?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%203"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;600851475143 の素因数のうち最大のものを求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;いきなり難易度が上がりました。素因数分解の問題です。
結局のところ片っ端から割ってみるしかないのですが、探索範囲を狭めることはできます。&lt;/p&gt;

&lt;p&gt;正の整数の範囲で考えると、l = m * nかつm &gt;= nであれば、floor(sqrt(l)) &gt;= nであることが直感的に分かります。ここでfloorは実数を0の方向に丸めて整数にする関数、sqrtは平方根を返す実数関数です。
nが分かれば、mは除算で求められます。つまりlが与えられた時、それを2つの因数に分解するのに探索する範囲は高々2 .. floor(sqrt(l))で十分ということです。
2つに分けられたならこっちのもの、得られたmとnを再帰的に分解して、その結果を合わせれば素因数分解の結果が得られます。
アルゴリズムを書き下すと次のようになります：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;n &amp;lt;- floor(sqrt(l))とする。&lt;/li&gt;
&lt;li&gt;n = 1なら、これ以上は分解できない（lは素数である）のでlをそのまま返す。&lt;/li&gt;
&lt;li&gt;nがlの因数なら、m &amp;lt;- l / nとし、mとnに対してこのアルゴリズムを再帰的に適用し、その結果を連結して返す。&lt;/li&gt;
&lt;li&gt;因数でないなら、n &amp;lt;- n - 1とし、2.から繰り返す。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;これで計算は可能です。しかしもう少し最適化を検討してみましょう。&lt;/p&gt;

&lt;p&gt;偶数は一般に2mの形で表せます。同様に奇数は2m + 1と書けます。
偶数同士の積は2m * 2n = 4mnとなり、l = 2mnとおけば2lなのでこれも偶数です。
奇数同士の積は(2m + 1)(2n + 1) = 4mn + 2(m + n) + 1であり、l = 2mn + m + nとすると2l + 1なのでこれも奇数です。
偶数と奇数の積は2m(2n + 1) = 4mn + 2mなので、l = 2mn + mとおいて2lなので偶数です。
つまり、奇数の因数は必ず奇数のみから成るということが分かります。先ほどのアルゴリズムでは、4.のステップでn &amp;lt;- n - 1としていました。これではlとnが両方とも奇数の時、1回不要な繰り返しが生じることになります。つまりこの場合を特別扱いして、n &amp;lt;- n - 2とすれば繰り返しを減らすことができます。
幸い、問題で与えられた600851475143という数値は奇数なので、この最適化の恩恵を十分に受けることができます。&lt;/p&gt;

&lt;p&gt;この最適化を施したところ、40%ほど高速化しました。上の考察におけるlはn、nはdivという名前になっています。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(define (divisor-of? n m) (zero? (modulo m n)))
(define (factorize n)
  (define div (inexact-&amp;gt;exact (floor (sqrt n))))
  (define (factorize-1 n div)
    (cond
     ((= div 1) (list n))
     ((and (odd? n) (even? div)) (factorize-1 n (- div 1)))
     ((divisor-of? div n) (append (factorize (/ n div)) (factorize div)))
     ((odd? n) (factorize-1 n (- div 2)))
     (else (factorize-1 n (- div 1)))))
  (factorize-1 n div))
(define (solve)
  (apply max (factorize 600851475143)))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;追記&lt;/h3&gt;

&lt;p&gt;コメントの匿名氏のコードを基にしたところ500倍高速になりました。よって上記の議論は忘れて手続き的に書いた方が良さげ。
多値を扱うのにSRFI-8の&lt;code&gt;receive&lt;/code&gt;マクロを使っています。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(define (divisor-of? m n) (zero? (modulo n m)))
(define (factorize n)
  (define (factorize-1 n i result)
    (cond
     ((&amp;lt; n (* i i)) (reverse (if (= n 1) result (cons n result))))
     ((divisor-of? i n) (factorize-1 (/ n i) i (cons i result)))
     (else (factorize-1 n (+ i 2) result))))
  (receive (n result)
           (let prepare-loop ((n n) (result '()))
             (if (divisor-of? 2 n) (prepare-loop (/ n 2) (cons 2 result))
                 (values n result)))
           (factorize-1 n 3 result)))
(define (solve)
  (apply max (factorize 600851475143)))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-5971514200397623451?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/5971514200397623451/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-3.html#comment-form' title='2 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5971514200397623451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/5971514200397623451'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-3.html' title='Project Euler - Problem 3'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-3255938235293327639</id><published>2009-03-18T23:43:00.006+09:00</published><updated>2009-03-22T03:39:14.353+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 2</title><content type='html'>&lt;h2&gt;問題&lt;/h2&gt;

&lt;p&gt;4,000,000以下のフィボナッチ数列の偶数の総和を求める問題です。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=2"&gt;原文&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%202"&gt;日本語訳&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;これまた悩む部分はなし。フィボナッチ数列は指数関数的に大きくなるので、かなり早く答えが出ます。
SRFI-1の&lt;code&gt;first&lt;/code&gt;と&lt;code&gt;second&lt;/code&gt;はそれぞれリストの最初と次の要素を返すユーティリティ関数です。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)
(define (solve)
  (define fibos
    (let gen-fibos-loop ((fibos '(1 1)))
      (define next-val (+ (first fibos) (second fibos)))
      (if (&amp;gt; next-val 4000000) fibos
          (gen-fibos-loop (cons next-val fibos)))))
  (apply + (filter even? fibos)))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-3255938235293327639?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/3255938235293327639/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-2.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3255938235293327639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/3255938235293327639'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-2.html' title='Project Euler - Problem 2'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-9105723814100511318</id><published>2009-03-18T23:09:00.007+09:00</published><updated>2009-06-21T11:56:37.680+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Project Euler - Problem 1</title><content type='html'>&lt;p&gt;まず1問目から。日本語訳を公開してくれている&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Project%20Euler"&gt;Wiki&lt;/a&gt;があるのでそちらのページもリンクすることにします。&lt;/p&gt;

&lt;h2&gt;問題&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=1"&gt;原文&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Find the sum of all the multiples of 3 or 5 below 1000.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://odz.sakura.ne.jp/projecteuler/index.php?Problem%201"&gt;日本語訳&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;1,000 未満の 3 か 5 の倍数になっている数字の合計を求めよ。&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;解答&lt;/h2&gt;

&lt;p&gt;最初の問題だけあって、別段難しくもありません。ほとんどFizzBuzz問題です。
0から999まで、公差1の等差数列から3あるいは5の倍数を抽出して合計すればいいわけです。
Scheme(Gauche)で書いてみました。&lt;code&gt;multiple-of?&lt;/code&gt;は&lt;code&gt;n&lt;/code&gt;が&lt;code&gt;m&lt;/code&gt;の倍数かどうかを示す述語で、&lt;code&gt;iota&lt;/code&gt;はSRFI-1に収録されているリスト構築子です。&lt;/p&gt;

&lt;pre class="prettyprint lang-scm"&gt;&lt;code&gt;(use srfi-1)
(define (multiple-of? n m) (zero? (modulo n m)))
(define (solve)
  (apply + (filter (lambda (n) (or (multiple-of? n 3) (multiple-of? n 5)))
                   (iota 1000))))
(define (main argv)
  (display (solve))
  (newline))
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-9105723814100511318?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/9105723814100511318/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-1_18.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/9105723814100511318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/9105723814100511318'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/project-euler-problem-1_18.html' title='Project Euler - Problem 1'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1815593124211758484.post-411445237462381507</id><published>2009-03-16T00:39:00.005+09:00</published><updated>2009-03-21T23:13:34.506+09:00</updated><title type='text'>0th post</title><content type='html'>&lt;p&gt;ようこそ。ここは情報工学を学ぶ一学生のブログです。&lt;/p&gt;

&lt;p&gt;4月から大学編入生になるので、これからの学習記録や作ったものを公開していきたいと思います。
3月中は準備運転。当面は以前から挑戦していた&lt;a href="http://projecteuler.net/"&gt;Project Euler&lt;/a&gt;でも進めていきます。&lt;/p&gt;

&lt;p&gt;本ブログの目標：
&lt;ul&gt;&lt;li&gt;3日に1回以上更新、コンスタントに！&lt;/li&gt;&lt;li&gt;文体はこだわらない。&lt;/li&gt;&lt;li&gt;ジャンルもこだわらない。ただし中心はプログラム。&lt;/li&gt;&lt;li&gt;私的なことや妄想はmixi。&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;ぼちぼちやっていきます。フィード購読してね！&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1815593124211758484-411445237462381507?l=outer-inside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://outer-inside.blogspot.com/feeds/411445237462381507/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://outer-inside.blogspot.com/2009/03/0th-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/411445237462381507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1815593124211758484/posts/default/411445237462381507'/><link rel='alternate' type='text/html' href='http://outer-inside.blogspot.com/2009/03/0th-post.html' title='0th post'/><author><name>Koichi SATOH</name><uri>https://profiles.google.com/109414665961543470147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-VS7aGoOTbaU/AAAAAAAAAAI/AAAAAAAAAEI/LdbxfKHADYI/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
