论坛首页 编程语言技术论坛

[元编程系列] nil? respond_to?

浏览 2209 次
精华帖 (0) :: 良好帖 (16) :: 新手帖 (0) :: 隐藏帖 (1)
作者 正文
   发表时间:2009-03-19   最后修改:2009-04-19
都是一些老东西.

ICK是 invocation construction kit 的缩写,里面是什么呢,就是一些 Monad 吧。

http://ick.rubyforge.org/

安装:
gem install ick


一个经常出现的结构:
@person ? @person.name : nil


我们觉得像下面这样写就够了:
@person.name


为了达成上面的目标,我们可能会这样做:
class NilClass
  def method_missing name, *args
    nil
  end
end


不过有些代码倒是希望nil.name会弹出一个异常,所以也有另外一个方法:try()
class Object
  def try method
    __send__ method if respond_to? method
  end
end


结果就是写成
@person.try :name  # 这样也显示了检查@person是否nil的意图

但是呢,使用ick,可以做到更强大的链式try哦~~

先看一段比较烦的代码
a.b.c.d.e.f if a && a.b && a.b.c && a.b.c.d && a.b.c.d.e

再看一段更令人烦躁的代码
a.b.c.d.e.f if a.respond_to?(:b) && a.b.respond_to?(:c) && a.b.c.respond_to?(:d) && a.b.c.d.respond_to?(:e) && a.b.c.d.e.respond_to?(:f)


我们要把 if 后面那段去掉!

为此先对Object添加特性: maybe和try
require 'ick'
class Maybe < Ick::Guard
  guard_with { |value, sym| value }
  evaluates_in_calling_environment and returns_result
  belongs_to Object
end
class Try < Ick::Guard
  guard_with { |value, sym| value.respond_to? sym }
  evaluates_in_calling_environment and returns_result
  belongs_to Object
end


现在我们有舒服的写法了~~~

下面方法链中,只要其中一个环节产生了nil,就返回nil
maybe(a){ |x| x.b.c.d.e.f }


下面方法链中,只要其中一个环节方法没有定义,就返回nil
try(a){ |x| x.b.c.d.e.f }


补充

为什么采用这样的结构?直接 try(a).b.c.d.e.f 不是更好么?

因为:从try(a)起,b,c,d,e,f 都是原对应对象的代理,最后产生的东西和原本期待的 a.b.c.d.e.f 差别很大……

所以,这段代码放在block里面,就可以把最后返回的值还原成干干净净的对象。

2009.4.19 补充:

ICK 让我们从另一个方式思考问题——Maybe Monad,但是,ruby 和 python 对象本身已经是 Maybe Monad 了…… 所以还是显得有点不必要。

a.b.c.d.e.f rescue nil
   发表时间:2009-03-19  
wow,方便。这个方法我要借用一下……
0 请登录后投票
   发表时间:2009-03-19  
可以看http://ick.rubyforge.org/inside.html

其实本来想写rewrite来着……
0 请登录后投票
   发表时间:2009-03-19  
我觉得不好看,我用另一种方式
try.xxx.yyy.zzz.default('abc')
try.xxx.yyy.default
"price: #{try.nil1.nil2.price.default(0)}"

大家先批批,我明天整代码上来
0 请登录后投票
   发表时间:2009-03-19  
lllyq 写道
我觉得不好看,我用另一种方式
try.xxx.yyy.zzz.default('abc')
try.xxx.yyy.default
"price: #{try.nil1.nil2.price.default(0)}"

大家先批批,我明天整代码上来


似乎
try.xxx.yyy || 'abc'
更舒心?

如果别人写了try = nil怎么办...
0 请登录后投票
   发表时间:2009-04-18  
暂时还体会不到ick的用处,貌似这些功能都是强大的method_missing的作用..
0 请登录后投票
   发表时间:2009-04-19  
没有groovy的gpath漂亮,用'?'就解决了
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics