2013-03-28 31 views
4

我想写一个或帮助器(基于Not Method by Jay Fields)。我想实现的是:Ruby:访问方法链中的调用方

s = "" 
s.nil?    # false 
s.empty?   # true 
s.nil? || s.empty? # true 
s.nil?.or.empty? # should == true 

我可以访问的nil?的结果,但不是什么输入nil?了。

我得到:

NoMethodError: undefined method `empty?' for false:FalseClass 

这甚至可能吗?

注意:这需要是原生ruby 不是轨道!

+0

我想我已经完成了,如果您有任何困惑,请查看答案和评论。 –

回答

1

你不能做到这一点。

s.nil?返回值是truefalse,它们是分别TrueClassFalseClass,唯一的实例。您不能创建这两个类的其他实例。所以你不能猴子补丁TrueClassFalseClass记住上下文s。您可以在truefalse上定义单身方法or,但是它对s一无所知,因此您无法链接另一个谓词empty?

def true.or other 
    true 
end 

def false.or other 
    other 
end 

您可以用定义的两个辅助方法编写s.nil?.or(s.empty?)

另一个想法是返回所有谓词(blabla?)方法的自定义对象,而不是truefalse。然而,在红宝石中,只有nilfalse产生错误,其他任何东西都会产生错误。自定义对象的实例将始终为真,这将打破所有这些谓词方法。

0

试试这个

p RUBY_VERSION 
p s = "" 
p s.nil?    
p s.empty?   
p s.nil? || s.empty? 
p (s.nil? or s.empty?) 

输出:

"2.0.0" 
"" 
false 
true 
true 
true 

说明:

s.nil? 
#=> false 

s.nil?.or.empty? 
#NoMethodError: undefined method `or' for false:FalseClass 
#  from (irb):5 
#  from C:/Ruby200/bin/irb:12:in `<main>' 

因为s.nil?上述错误给falsefalseFalseClass的一个实例,并且此类没有or方法。所以实际的修复如上所示。

编辑

p RUBY_VERSION 
class Object 

alias :oldnil :nil? 

    def nil? 
    @@x = self 
    oldnil 
    end 
end 

class FalseClass 
    def or 
    empty? 
    end 

    def empty? 
    @@x.empty? 
    end 
end 

class TrueClass 
    def or 
    empty? 
    end 

    def empty? 
    @@x.empty? 
    end 
end 

s = "" 
p s.nil? 
p s.empty? 
p s.nil? || s.empty? 
p s.nil?.or.empty? 

输出:

"2.0.0" 
false 
true 
true 
true 
+0

这适用于这种特定的条件组合。我认为jamlen对更通用的解决方案感兴趣。此外,它不是线程安全的。 –