Try() 和 Maybe Monad

在Ruby里用到对象图导航(Object Graph Navigation)的时候,有时候需要判断对象是否为nil,很常见这样的代码:

#显示某个产品的分类名称
product.category ? product.category.name : nil

ozmm.org的chris最近介绍了一个好方法,他给这个方法起名叫[url=http://ozmm.org/posts/try.html]try()[/url],给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提供了一个[url=http://www.gnejs.net/2008/03/02/improved-try/]Improved 'try()'[/url],上面的代码可以简化成

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


但是又有人觉得这样不够直观了,提供了一个类似Groovy做法的: [url=http://www.urubatan.info/2008/03/a-better-try-for-ruby-why-not-do-the-groovy-way/]A better “try()” for Ruby, why not do the Groovy way?[/url]
Groovy语言本身提供了内置的?.操作: person?.name,而上面这篇文章则通过在方法名后面添加"_"来实现相同的目的

product.category.owner_.name_


Q1: 和方法2相比,它少了一个默认值的处理,大家觉得添加这样的特性如何?

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


上面这3种try()方法都是通过method missing实现的,这篇文章提到的[url=http://blog.pretheory.com/arch/2008/02/the_maybe_monad_in_ruby.php]Maybe Monad[/url]也可以解决这个问题:

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


Q2: 这些方法你更喜欢用哪一种呢?或者你有其他更好的方法?欢迎讨论。
我比较喜欢方法2,感觉代码侵入比较小,缺点是多层导航的时候不够直观。而方法4Maybe Monad的优缺点正好与之相反,如果能综合这2种方法就好了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值