jasagiri @ ウィキ
HelloFunctor
最終更新:
jasagiri
-
view
Hello Functor: pattern based method dispatch in ruby
June 18, 2008
ruby 界隈で一歩先へいく革新的なイニシアティブのひとつがWavesプロジェクトです。 これはrubyベースのウェブアプリケーションでオープンソースフレームワークです。 これは皆が「次世代」だと思うはずです。 これは美しく簡潔なコードで書かれています。 Lambdas はwavesでは非常にはっきりしています。 リソースの実装が マッピングを基礎付けました。 MVC パラダイム (せいぜい必要な)を調べ始める前にResources は一級市民です(?)
June 18, 2008
ruby 界隈で一歩先へいく革新的なイニシアティブのひとつがWavesプロジェクトです。 これはrubyベースのウェブアプリケーションでオープンソースフレームワークです。 これは皆が「次世代」だと思うはずです。 これは美しく簡潔なコードで書かれています。 Lambdas はwavesでは非常にはっきりしています。 リソースの実装が マッピングを基礎付けました。 MVC パラダイム (せいぜい必要な)を調べ始める前にResources は一級市民です(?)
このプロジェクトからデザインと実装の美しい2つの小さなgemが生まれました。 1つは Autocodeで
、クラスとモジュールを自動的に読み込みんだり生成したりするライブラリです。
Autocode に関する詳しい情報がここ(http://dev.zeraweb.com/introducing-autocode-0-9-9/)にあります。
、クラスとモジュールを自動的に読み込みんだり生成したりするライブラリです。
Autocode に関する詳しい情報がここ(http://dev.zeraweb.com/introducing-autocode-0-9-9/)にあります。
もうひとつは、私にとってより魅力的なもので Functor と呼ばれるシンプルで小さなgemです。それはここで詳しく説明します。これは Topher Cyll 氏が最近開発した multi gem の成果を元に作られています。
Waves プロジェクトからは独立した Functor の使用例。:
functor( :normalize, Symbol, Hash ) { | name, options | options.merge!( :name => name ) } functor( :normalize, String, Hash ) { | p, options | options.merge!( :pattern => p ) } functor( :normalize, Regexp, Hash ) { | re, options | options.merge!( :pattern => re ) } functor( :normalize, Exception ) { | exception | { :exception => exception } } functor( :normalize, Hash ) { | options | options }
これはこうやって呼ばれます。:
def map( *args, &block ) options = normalize( *args ) ...end
このコードは Functor 無しでどのようになるか考えてみてください。多分1ダースの入れ子の if-then-else や case-when などの構文になるでしょう。
さて、Functor はメソッドを多重定義するように振舞うように見えます。 java や C++ のような言語にはネイティブで存在しています。 Matz は「直交した特徴 [...] は複雑で爆発できる」(?)ため、ruby にメソッドの多重定義を実装するのを拒んでいます。 私は彼が正しいと思います。 Functor は直交性をこっそり許します。でもスタッフと一緒に船から落ちないでください。 あなたは正しいのですから。(?)
Functor の美しさはメソッドの多重定義以上のことを許容します。メソッドの多重定義することはクラスの引数の議論です。対照的に Functor は引数の引き当てにまず === 演算子を試し、それから == 演算子、そしてそれでもマッチしなかったら、あなたが提供している lambda や Proc(または何もあたらなければ :call が返されます) を試します。 このためこんなことが可能になるでしょう。:
functor( :get, /^foo$/ ) { |p| "foo!" } functor( :get, /^bar$/ ) { |p| "bar!" }
get("bar") を呼ぶと bar! が返ります
あなたはfunctorをgemでインストールして弄れます (source is http://gems.github.com/):
sudo gem install -r functor
または ソースコードは github で手に入れることができます。