Ruby Ruby 中没有 “逻辑与” 的短路原则吗?

rogerluo410 · 2015年12月28日 · 最后由 reyesyang 回复于 2016年01月03日 · 4995 次阅读
not instance.group_type.nil? and instance.group_type.downcase == "case" 

当第一个表达式为假时,即 group_type 为 nil 时,不会执行后面的第二个表达式。

现在的情况是,group_type 为 nil 时,任然会执行后面的表达式,然后就直接抛异常了“undefined method `downcase' for nil:NilClass”

请问,ruby 中有什么简单的方式 来处理这样的逻辑吗?

puts true and false  
puts (true and false)  
puts true && false  
puts true & false  
////~>  
true  
false  
false  
false  

找到答案了。。。

3 楼 已删除

可以明确告诉你,不是 ruby 的问题,好好想想吧 :)

#4 楼 @luikore

没发现,能不能指点迷津

[1] pry(main)> a = nil
=> nil
[2] pry(main)> not a.nil? and a.downcase
=> false
[3] pry(main)> not a.nil? and a.downcase == 'case'
=> false
[4] pry(main)> 

从 Ruby2.3 开始你可以用单身狗运算符了。

a&.downcase == 'case'

#6 楼 @msg7086 单身狗运算符…

你用中文把这个逻辑写出来,看看到底应该是『且』还是『或』

#6 楼 @msg7086 什么是 单身狗 运算符?

#9 楼 @nine 必然是「且」。基本等价于 t && t.downcase == 'case'

#10 楼 @u0x01 &. 运算符。

关注下,怎么做到的可以不短路的.....

题主的思路没错,就是句法太杂了。如果升到了 2.3 就赶紧用楼上的单身狗运算符,没有的话,判断一个对象是否为 nil 在代码中使用它本身就可以了(boolean 类型除外),没必要用 not + nil。

性能上也会有差别,not+nil 编译出来是这样的

0003 opt_send_simple  <callinfo!mid:a, argc:0, FCALL|VCALL|ARGS_SKIP>
0005 opt_send_simple  <callinfo!mid:nil?, argc:0, ARGS_SKIP>
0007 opt_not          <callinfo!mid:!, argc:0, ARGS_SKIP>
0009 dup              
0010 branchunless     22

而使用本身来判断只有一句

0003 opt_send_simple  <callinfo!mid:a, argc:0, FCALL|VCALL|ARGS_SKIP>
0005 dup              
0006 branchunless     18

用 Benchmark 试了下,效率差 30%

       user     system      total        real
simple  0.060000   0.000000   0.060000 (  0.064289)
complex  0.090000   0.000000   0.090000 (  0.092268)

@adamshen 太酷了!!这个编译后的结果是怎么查看的呢?

#14 楼 @dudu_zzzz 基本上就是这个类的方法http://ruby-doc.org/core-2.3.0/RubyVM/InstructionSequence.html

但是这个虚拟机的指令集我找了半天都找不到资料,只有日文资料。貌似 rubyspec 只描述 ruby 语言级行为,关于 ruby 虚拟机怎么实现其实并没有统一标准可循。你要是能找到 MRI 的指令集资料记得告诉我一声。

我是来赞单身狗运算符的...

@msg7086 “单身狗”运算符,可有典故?

直接 instance.group_type.to_s.downcase == "case",不就可以了吗

#17 楼 @qinfanpeng

“Look at this figure…and then…you can see…someone sitting on the floor looking at a dot. On the floor. By themself. Now you don’t forget. Yeah.”

---- yukihiro_matz

#19 楼 @msg7086 youtube 上的?视频能给个链接吗?

#19 楼 @msg7086 哈哈哈哈哈哈哈哈哈 我还以为是“对象是否存在”的运算符

#4 楼 @luikore 楼主理解没错啊

irb(main):009:0> class X; attr_accessor :group_type; end
=> nil
irb(main):010:0> instance = X.new
=> #<X:0x007fc43129ae30>
irb(main):011:0> not instance.group_type.nil? and instance.group_type.downcase == "case" 
=> false
irb(main):012:0> instance.group_type = 'case'
=> "case"
irb(main):013:0> not instance.group_type.nil? and instance.group_type.downcase == "case" 
=> true
irb(main):014:0> 

#22 楼 @fsword 是的 我自己看错了。

if instance.group_type && instance.group_type.downcase == "case" 这样不就解决了嘛

#19 楼 @msg7086 明明是“首先...”

msg7086 Ruby 安全调用运算符 (&.) 提及了此话题。 03月10日 01:08
需要 登录 后方可回复, 如果你还没有账号请 注册新账号