2010-09-11 42 views
1

我遇到了一个有趣的问题,下面是相对简单的作业。开始的每个括号内的块都评估为,而Rubygame::Surface.new应该被指定为@image的值。不幸的是,在我设置@rect的下一行中,它会抛出NoMethodError,因为@image简单'或'不按预期方式工作

@image = (image unless image.nil?) or 
     (Rubygame::Surface.autoload(image_file) unless image_file.nil?) or 
     (Rubygame::Surface.autoload("#{@name}.png") unless @name.nil?) or 
     Rubygame::Surface.new([16, 16]) 
@rect = Rubygame::Rect.new [0, 0], [@image.width, @image.height] 

类似的测试通过IRB工作按预期运行,所以我敢肯定的“或”语句是良好的,但我想不通为什么它没有返回新的表面时,一切否则是

+2

只有一条第一条线已经在吹我的头... – Nakilon 2010-09-11 10:05:33

+3

'image除非image.nil?' - >'图像如果图像 - >'图像' – Nakilon 2010-09-11 10:07:30

+0

重复的http://stackoverflow.com/questions/2083112/ – 2010-09-12 23:30:52

回答

5

orand关键字在Ruby中有非常,非常低的优先级。甚至低于赋值运算符=。因此,简单地分别用||&&(两者的绑定比=更紧密)替换它们,它应该按照您的预期工作。 Ruby的operator precedence is listed here

除此之外,我会说你的代码非常密集。考虑将其重构为如下所示的内容,我认为它更好地传达了代码的意图。

@image = case 
    when image then image 
    when image_file then Rubygame::Surface.autoload(image_file) 
    when @name then Rubygame::Surface.autoload("#{@name}.png") 
    else Rubygame::Surface.new([16, 16]) 
end 

@rect = Rubygame::Rect.new [0, 0], [@image.width, @image.height] 
+0

运算符优先级是我版本中的问题,但我试图使用您的案例版本,并且仍然返回_nil_。方法参数满足第一个when-condition('image = Rubygame :: Surface.new([640,480])'),但是如果你省略case语句的参数,它与之比较的是什么? – harbichidian 2010-09-11 15:18:20

+0

这里使用'case'的方式,没有参数,只是在'when'之后测试每个表达式的真实性。当它找到第一个真值时停止。在我给出的例子中,将'nil'分配给'@ image'的唯一方法是在特定情况下'Rubygame :: Surface.autoload'或'Rubygame :: Surface.new'返回'nil'。 – molf 2010-09-11 22:57:21

1

您是否尝试了更高水平的括号?

@image = ((image unless image.nil?) or 
     (Rubygame::Surface.autoload(image_file) unless image_file.nil?) or 
     (Rubygame::Surface.autoload("#{@name}.png") unless @name.nil?) or 
     Rubygame::Surface.new([16, 16])) 
+0

在这些和/或任何Ruby情况下尝试一个很好的通用事物。这是解决我有条件问题的90%的解决方案。 – 2010-09-11 10:01:47

+2

我只记得Perl的'或'具有比'||'和'='更低的优先级。编写代码充斥着括号,直到我明白为止。 – amphetamachine 2010-09-11 10:11:43

-1

为什么使用RubyGame?用于Ruby的Gosu游戏开发框架更快,更受欢迎。