Try()とMaybe Monad


Rubyでオブジェクトマップナビゲーション(Object Graph Navigation)を使用する場合、オブジェクトがnilかどうかを判断する必要がある場合があります.このようなコードはよくあります.

#           
product.category ? product.category.name : nil

ozmm.orgのchrisは最近良い方法を紹介して、彼はこの方法に名前をつけました
try()、Objectにtryメソッドを追加します.

class Object
  def try(method)
    send method if respond_to? method
  end
end

これにより、上記のコードは

product.category.try(:name)

このtryの実際の用途はたくさんあります.例えば、

#           
User.find_by_name("JavaEye").try(:destroy)
#              
User.find_all_by_active(false).last.try(:name)

しかし、この簡単なtry()には多くの制限があります.例えば、元のコードでは解決できません.

#   
product.category ? product.category.name : "N/A"
#       
product.category.owner.name

これに対してAnders Engströmは
Improved 'try()'、上記のコードは

product.category.try(:name, :default => "N/A")
product.category.try(:owner, :name)

しかし、直感的ではないと感じている人もいます.Groovyのような方法を提供しています.
A better “try()” for Ruby, why not do the Groovy way?
Groovy言語自体は内蔵されていますか?の操作:person?name、上の文章はメソッド名の後ろに「」を追加します.同じ目的を達成するために

product.category.owner_.name_

Q 1:メソッド2に比べてデフォルト値の処理が少なくなっていますが、このような特性を追加してみてはいかがでしょうか.

product.category.name_(:default => "N/A")

上記の3つのtry()メソッドはmethod missingによって実現されていますが、この記事では
Maybe Monadもこの問題を解決することができます.

Maybe.new(product).category.name.value("N/A")

Q 2:これらの方法はどちらが好きですか.それとも他にもっと良い方法がありますか?討論を歓迎する.
私は方法2が好きで、コードの侵入が小さいと感じて、欠点は多層ナビゲーションの時に直感的ではありません.一方,メソッド4 Maybe Monadの長所と短所は正反対であり,この2つのメソッドを統合できればよい.