=head1 名前 autobox::Core - Perl 組み込み関数をプリミティブ型のメソッドに =head1 概要 use autobox; use autobox::Core; "Hello, World\n"->uc()->print(); =head1 説明 数値, 文字列, 配列, ハッシュ, そしてコードリファレンスを操作する F組み込み関数をラップするメソッド. 厄介なデリファレンス構文や 括弧の衝突を避けるために組み込み関数をメソッドして利用するのに便利です. L はオブジェクトリファレンスではないスカラーに対して メソッド呼び出しを提供します. 数値, 文字列, 数値を含んだスカラー, 文字列を含んだスカラー, 配列リファレンス, ハッシュリファレンス, そしてコードリファレンス全てオブジェクトとして動作します. L は L にこの機能を提供しますがそれ自身では 呼び出されるメソッドを何も提供しません. それはユーザやその他の モジュールに任されています. そう, 例えば今見ているこのモジュール. F はあなたの呼び出す I<スタブ> モジュールです. これは単に接着剤(glue)であり, 既存の関数を新しいインターフェースで 表現しています. ほとんどの関数は C<< sub hex ($) { hex($_[0]) } >> の ように読み取ります. ハッシュ, 配列, スカラー, そしてコードリファレンスを操作する ビルトイン関数に加えて, いくつかの Perl 6 的なものも投入されて います. そして C の様な幾つかのキーワードもメソッドに なっています. =head2 何が実装されているのか L の中で次の見出しでリストアップされている全ての関数: "実際の @ARRAY に対する関数(Functions for real @ARRAYs)", "実際の %HASH に対する関数(Functions for real %HASHes)", "リストデータに対する関数(Functions for list data)", そして "SCALAR 若しくは文字列に対する関数(Functions for SCALARs or strings)", 加えて後述の他の セクションやドキュメントから取ってきたいくつか. Perl 6 で予定されている幾つかの事項, C, C, そして C が投入されています. L, C と conjuction して 使うためには明示的に配列を平坦にする(flatten)する必要があります. 組み込みのものの, データに対してとてもよく使う物は全て実装されています. ちょっとした例: print [10, 20, 30, 40, 50]->pop(), "\n"; print [10, 20, 30, 40, 50]->shift(), "\n"; my $arrref = [10, 20, 30]; my $lala; $lala = "Lalalalala\n"; print "chomp: ", $lala->chomp(), ' ', $lala, "\n"; $lala = "Lalalalala\n"; print "lcfirst: ", $lala->lcfirst(), ' ', $lala, "\n"; my $hashref = { foo => 10, bar => 20, baz => 30, qux => 40 }; print "hash keys: ", join ' ', $hashref->keys(), "\n"; L のこれらのセクションの傍で C, C, C, C, C, そして C, をそれらが意味をなすように実装しました. C, C, そして C はコードリファレンスでは動作せず, C はリファレンスではないスカラーでは動作しません. C はリファレンスではないスカラーで動作し, 正規表現操作は C, C, そして C で行えます. my $arr = [ 1 .. 10 ]; $arr->undef; 配列リファレンスは要素数や最後の要素の添字を知ることが出来ます. my $arr = [ 1 .. 10 ]; print '$arr contains ', $arr->size, ' elements, the last having an index of ', $arr->last, "\n"; 配列リファレンスはその要素をダンプするために C メソッドを 持っています. これは C<< @{$array_ref} >> と同じです. my $arr = [ 1 .. 10 ]; print join " -- ", $arr->flatten, "\n"; L の影響下では以下と等価なコードを書く必要があります: use Perl6::Contexts; use autobox; use autobox::Core; my @arr = ( 1 .. 10 ); do_something(@arr->flatten); 配列リファレンスは C 及び C を使ってイテレーションする 事も出来ます. どちらも for 文の本体としてコードリファレンスを 取ります. C は各取り渡しの中で現在のエレメント自身を 渡します. C はコードブロックに現在の要素のインデックス, そして現在の 要素, さらに配列自身のリファレンスを渡します. my $arr = [ 1 .. 10 ]; $arr->foreach(sub { print $_[0], "\n" }); $arr->for(sub { die unless $_[1] == $_[2]->[$_[0]] }); C は L っぽいことをするおもちゃぽっけです: print $arrref->sum(), "\n"; これがうまくいくことを吟味した上で, L に依存して その関数を適切なデータに対するメソッドとして露出させようと思います. 若しくはとりあえずで行うかもしれません. C は C と似ていますがハッシュリファレンスに対して 行います. ハッシュの中の各キーに対して, 引数にキーと対応する値を つけてコードリファレンスを呼び出します: my $hashref = { foo => 10, bar => 20, baz => 30, quux => 40 }; $hashref->each(sub { print $_[0], ' is ', $_[1], "\n" }); 今のところコードブロックに渡す前に要素をソートする方法はありません. もし誰かがソートの判断基準を渡す方法を求めたら実装するでしょう. C は C<< m// >> で C は C<< s/// >> です. これらはスカラー に対して動作します. C<< qr// >> で作成した正規表現と, L で記述されている C<< (?imsx-imsx) >> 構文を使った正規表現の一部 として正規表現へのフラグを指定します. C は配列リファレンスを 返すので, C や C といった物をその結果に対して呼び出す 事も出来ます. my ($street_number, $street_name, $apartment_number) = "1234 Robin Drive #101"->m(qr{(\d+) (.*)(?: #(\d+))?})->elements; print "$street_number $street_name $apartment_number\n"; C はリファレンスではないスカラーに対して正規表現を伴って 呼び出します. これは C 及び C と同じです. print "10, 20, 30, 40"->split(qr{, ?})->elements, "\n"; コードリファレンスを C 化することも出来ます. $adding_up_numbers = sub { my $first_number = shift; my $second_number = shift; return $first_number + $second_number; }; my $adding_five_to_numbers = $adding_up_numbers->curry(5); $adding_five_to_numbers->(20)->print; "\n"->print; 以上. =head2 足りない部分 演算子. でももう疲れたよ. それは朝にやるよ. 多分. パッチおくっといて. ファイルとソケットの操作は L と L の方でオブジェクト指向的に実装されています. L の以下の見出しでリストアップされている物: "System V プロセス間通信関数(System V interprocess communication functions)", "ユーザ及びグループ情報の取得(Fetching user and group info)", "ネットワーク情報の取得(Fetching network info)", "perl モジュールに関連するキーワード(Keywords related to perl modules)", "プロセスとプロセスグループに対する関数(Functions for processes and process groups)", "スコープに対する関数(Keywords related to scoping)", "時間関係の関数(Time-related functions)", "perl プログラムのフロー制御に関するキーワード(Keywords related to the control flow of your perl program)", "ファイルハンドル, ファイル, 若しくはディレクトリに対する関数(Functions for filehandles, files, or directories)", そして "入出力関数(Input and output functions)". これらは他のCPANモジュールによってオブジェクト指向に実装されてそう なもの, 関数ではなくキーワード, 引数を取らない物, それか 文字列, 数値, 配列, ハッシュ, コードのAPIとして意味がないもの たちです. C は使うべきではないでしょう. C はハッシュに対して. それがないことの上手な理由はありません. =head2 autobox化 I<このセクションでは私, Scott Walters による Perl 6 Now: The Core Ideas Illustrated with Perl 5 から4ページを引用しています. テキストは本の248ページ からあります. このコピーは複製の利益を欠いています - 完成した製品は より高品質です. Perl 6 Now のオーダーに関しては SEE ALSO セクションの 無恥な広告を参照してください. > I とはプリミティブ変数を含んでいるオブジェクトです. box には プリミティブ型に対してオブジェクトとしての機能を賦与する為に 使われます. これは強く型付けされた言語での要素であって厳密には Perl には必要のない物です. プログラマは C<< my $number = Int->new(5) >> と書くこともできます. これは手作業のbox化です. I (自動box化) とは簡単な型をオブジェクト型に自動的に変換すること若しくはその 概念です. これは言語によって行われます. これはプログラマに言語の インタプリタがデータ格納域の実装は自由であるにもかかわらず 全てがオブジェクトであるかのように見せます. autobox は実際に数値, 文字列, 配列といった簡単な型をオブジェクトとして 具現化します. C, C, C, C, そして他の小文字の名前の型は プリミティブです. これらは操作が速く, 格納の際にデータが厳密に必要と するより余計なメモリを必要としません. C, C, C, C そして1文字目が大文字になっているその他の型はオブジェクトです. これらはサブクラス化(他から派生)していて, 特徴その他を受け継いでいる でしょう. これらのオブジェクトはプリミティブ型をオブジェクトとして 表現するというただ1つの目的のためにシステムによって提供されて いますが, これには C や C を機能させるといった多くの補助的な 利益ももたらします. Perl は C をくるむために C を, C をくるむために C を, C をくるむために C を, 等々を提供します. Perl のハッシュや動的に拡張可能な配列の実装は オブジェクトだけでなく任意の型を格納できるため, Perl プログラマは プリミティブ型をオブジェクトにbox化する必要はほとんどありません. Perl の力はこの機能を他の言語が行うより本質でなくしています. X autobox化はプリミティブをオブジェクトとし, それはbox化した ものと等価です. C はコンストラクタを呼び出したり渡したりを全く することなしに C として使うことができます. # Perl 6 - autoboxing associates classes with primitives types: # Perl 6 - autobox 化はクラスとプリミティブ型を結びつけます. print 4.sqrt, "\n"; これは完全に有効な Perl 6 の文です. これはハッシュや配列にも同様に適用できます: # Perl 6 - autoboxing associates classes with primitive types: # Perl 6 - autobox 化はクラスとプリミティブ型を結びつけます. print [ 1 .. 20 ].elems, "\n"; 言語ではデータ格納域を好きなように実装できますが, プログラマからは 変数がオブジェクトであるかのように見えます. autoboxを利用する式はラテン接尾辞のような何かのように読めます. autoboxの精神では, 何かをより"mnemonic"にするというのではなくて, それが "mnemonicified" されると言います. autobox化は通常の関数呼び出しと混在できます. メソッドが関数として 利用可能であり関数がメソッドとして利用可能である場合には, 式を どう記述するかは個人の嗜好に任せられています. # Calling methods on numbers and strings, these three lines are equivalent # Perl 6 # 数字と文字に対してメソッドの呼び出し, この3行は Perl 6 的に等価です. print sqrt 4; print 4.sqrt; 4.sqrt.print; これら3つのうち最初の1つはグローバルな C 関数が存在することを 仮定しています. このグローバル関数が削除され C パッケージにのみ 残った場合には最初の例は失敗します. Perl 5 ではファイルハンドルの autobox 化を始めました. use IO::Handle; open my $file, '<', 'file.txt' or die $!; $file->read(my $data, -s $file); ここで, C は私たちが開いたファイルハンドル上のメソッドですが それはI<全く bless されていません>. これは曖昧な C<< print $file ... >> ではなく C<< $file->print(...) >> のようなものと言わせます. 多くの人々の多くの時間のために, これは同様により概念の意味を作ります. =head3 プリミティブ型をBox化する理由 これは結局何の役に立つの? =over 1 =item オブジェクトインターフェースを使っているプログラマにオプションを処理 するためのI<その>方法として概念的な感覚を生み出します. =item もう一つの表現. プログラマに複雑な手続きルールや奇妙な演算子を 読み書きさせる必要がありません. =item 長大な式を補うための括弧が必要になる多くの状況では少しのプリミティブ型 に括弧を補うだけに書き換えることができるでしょう. =item コードをより少ないテンポラリ変数で書き直すことができます. =item autobox はオブジェクトが実際にプリミティブ型を表現するために メモリをふくらませることなしに box された型の恩恵を提供します. autobox は"それを擬装" します. =item 文字列, 数値, 配列, ハッシュ, その他はそれぞれ別々のAPIを持っています. 配列用の C メソッドのドキュメントではハッシュでそれが どのように処理されるかを説明する必要はありません. =item Perl は文の"主語"は行の先頭に置くべきであるという提案を試みていて, そして autobox はこれを促進しています. =back Perl は慣用句的な言語であり, これは重要な表現です. =head3 主語を先頭に: 余談 Perl の設計哲学では, 言語はプログラマに文の先頭にX<主語>主語を置く のを許せるくらい十分に柔軟であるべきとあります. 例えば, C<< die $! unless read $file, 60 >> はこの文の第一の目的が C で あるように見えます. それがプログラマの第一の目的と思いますが, そうでないときにはプログラマは彼の第一の目的を全く同じロジックを 保ったまま節の順序を反転させることで意思の疎通をとることができます: C<< read $file, 60 or die $! >>.autobox は主語を先頭に置く もう一つの方法です. 関数やメソッドは同士です. C<< $noun->verb() >> は動作が処理されることではなく 動作の対象となるそのものに読み手の注意を引くでしょう. C<< $verb($noun) >> と比較してみてください. =head3 autobox化とメソッドの結果 第11節 [サブルーチン] で, 式を記述する方法を例示しました. ここでまた示します: # Various ways to do the same thing: # 同じことをするために様々な方法があります: print(reverse(sort(keys(%hash)))); # Perl 5 - pathological parenthetic # Perl 5 - 病的な括弧 print reverse sort keys %hash; # Perl 5 - no unneeded parenthesis # Perl 5 - 不要な括弧を削除 print(reverse(sort(%hash,keys)))); # Perl 6 - pathological # Perl 6 - 病的 print reverse sort %hash.keys; # Perl 6 - no unneeded parenthesis # Perl 6 - 不要な括弧を除去 %hash.keys ==> sort ==> reverse ==> print; # Perl 6 - pipeline operator # Perl 6 - パイプライン演算子 %hash.keys.sort.reverse.print; # Perl 6 - autobox %hash->keys->sort->reverse->print; # Perl 5 - autobox この節ではこれら等価な式の中で最後の2つを扱います. 次のようなメソッド呼び出しを考えてみます: use autobox; use autobox::Core; use Perl6::Contexts; my %hash = (foo => 'bar', baz => 'quux'); %hash->keys->sort->reverse->print; # Perl 5 - autobox # prints "foo baz" この例においては, 各メソッド呼び出しは配列リファレンスを返します. 他のメソッド呼び出しはその値を直ぐに処理しています. 前の呼び出しの結果で次のメソッド呼び出しをするこの間隔は autobox の利用における一般的な用法です. メソッド呼び出しに何の 引数も与えていないのは一般的というわけではありませんが. F はオブジェクトのコンテキストが C<< -> >> によって 定まることを認識して, C<%hash> をF を利用するのに適切な リファレンスへと変換します. F は様々な種類のリファレンスの ようなプリミティブ型を, クラスに関係させます. F は Perl の組み込み関数をラップしているそれらのクラスのメソッドに 投げます. 全容を開示した背景に, F と F は私の制作ということもあります. =head3 式を簡単にするための autobox プログラミングにおいて私のお得意のいらいらの一つに, 長くなった式を補うための括弧があります. それは行の始めで開いた括弧を閉じる準備をする時間のような物で, 忘れていた何かを思い出し, 矢印で戻るかマウスを捕まえなければなりません. 式が1行に納めるのには長すぎてしまったときには, それは分解され, 3行とかそれ以上であればどんな風にインデントするかも決めなければ なりません. # Perl 5 - a somewhat complex expression # Perl 5 - 何か複雑な式 print join("\n", map { CGI::param($_) } @cgi_vars), "\n"; # Perl 5 - again, using autobox: # Perl 5 - もう一度, 今度は autobox で: @cgi_vars->map(sub { CGI::param($_[0]) })->join("\n")->concat("\n")->print; autobox を利用したバージョンは短いわけではありませんが, それは 左から右に読むことが出来, C の括弧はたいした量の文字を囲む こともありません. autobox を使わないバージョンにある C される値を提供している複雑な式は, autobox を利用するバージョン では, C メソッドを呼びだす元の値になっています. この C 文は CGI パラメータ名のリストを取り, 各パラメータの 値を読み, それらを改行でつなぎ合わせ, そして最後に改行をつけて 出力しています. 敢えてこの式がより長く複数行に分ける必要があるとしたら, それか各式要素にコメントをおくとしたら, それは次のようになるでしょう: @cgi_vars->map(sub { CGI::param($_[0]) }) # turn CGI arg names into values # CGI 引数名を値に. ->join("\n") # join with newlines # 改行で連結. ->concat("\n") # give it a trailing newline # 末尾の改行を追加. ->print; # print them all out # それら全部を出力. 若しくはこのようにも書けるでしょう: sub { CGI::param($_[0]) }->map(@cgi_vars) # turn CGI arg names into values # CGI 引数名を値に. ->join("\n") # join with newlines # 改行で連結. ->concat("\n") # give it a trailing newline # 末尾の改行を追加. ->print; # print them all out # それら全部を出力. C は X<多態>多態性を持っています. C パッケージで 定義されている C メソッドは引数に map する対象物をとります. C パッケージに定義されている C は配列の各要素に 適用させるコードリファレンスをその引数によります. I =head1 バグ はい. それは作者, L に送って下さい. このコードはそんなにテストされていません. API もまだ確定していません - Perl 6 的な物やローカルな拡張は 今後もリネームされるかもしれません. =head1 履歴 Version 0.3 では C が Perl 5.8.6 かおそらく 5.8.5 で 導入されたテストのために十分な引数を伴っていない問題を修正しました. この現象は Ron Reidy から報告されました - ありがとう Ron! Version 0.3 では Perl 6 Now と抜粋へのリファレンスを追加 しました. Version 0.2 では API を完成させ, 関数的なメソッドを始めてみました. Version 0.1 は悲しいくらい不完全でした. =head1 関連項目 L. L. Perl 6: L<< http://dev.perl.org/perl6/apocalypse/ >>. (広告警告!) I はその第14節, オブジェクトのかなりの部分を, autoboxにさいていて, またその発想は全体を通して強く使われています. 第8節, データ構造 にも多数の例があります. 詳しい情報は L か, お気に入りの書店で ISBN 1-59059-395-2 を確認してみて下さい. =head1 著者 Scott Walters, L chocolateboy, L を, そして激励をありがとう! =head1 和訳 山科 氷魚 (YAMASHINA Hio) 原典: autobox-Core VERSION 0.3. 翻訳日: 2006-10-26.