Hatena::Grouprubyist

Going My Ruby Way このページをアンテナに追加 RSSフィード

Ruby ロゴ (C) Ruby Association LLC

2011年07月22日(金)

カスケード (Object の拡張)

| 22:08 |  カスケード (Object の拡張) - Going My Ruby Way を含むブックマーク はてなブックマーク -  カスケード (Object の拡張) - Going My Ruby Way  カスケード (Object の拡張) - Going My Ruby Way のブックマークコメント

Object を拡張してカスケードパターンを実装します。

Object のようなコアな部分を拡張するのはどうかという議論もありますが、ここは Going My Ruby Way (略してGMRW) です。

カスケードは、同じレシーバに複数のメッセージを送るパターンです。

Smalltalk ベストプラクティス・パターン』に紹介されています。

(解釈が正しいかはあんまり自信がありません)

----

object.rb

#!/usr/bin/env ruby
# -*- coding :UTF-8 -*-

class Object
  def cascade!(&block)
    block.arity > 0 ? tap(&block) : instance_eval(&block)
    self
  end

  def cascade(&block)
    block ? cascade!(&block) : self
  end
end

# vi:set ts=2 sw=2 et fenc=UTF-8:

cascade! はブロックが渡されるのを期待します。渡されないと怒ります!

cascade はブロックが渡された場合のみブロックを実行します。温厚な性格です。

引数なしブロックが渡された場合は、ブロックを self の instance_eval で評価します。

引数ありのブロックが渡された場合は、self をブロックの1番目の引数として渡します。

casecade、casecade! とも self を返します。

----

例です。

>> "hello".cascade { upcase! }
=> "HELLO"

>> "hello".cascade {|s| s.upcase! }
=> "HELLO"

ブロックの中の upcase!upcase の場合、返る値は "hello" です。

casecade、casecade! とも self を返しますので。

======

ここまで、日記を書いて cascade! の実装を block.call(&block) から tap(&block) に変更しました。

cascade は、結局 tap のちょっとしたバリエーションな感じです。

----

参考書籍