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

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

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

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

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

共收到 27 条回复
puts true and false  
puts (true and false)  
puts true && false  
puts true & false  
////~>  
true  
false  
false  
false  

找到答案了。。。

#1楼 @rogerluo410

妈蛋, 还是不行

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
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册