【问题标题】:Simple 'or' isn't working as expected简单的“或”没有按预期工作
【发布时间】:2010-09-12 16:48:03
【问题描述】:

我在下面相对简单的分配中遇到了一个有趣的问题。开头的每个带括号的块都评估为 nil,留下 Rubygame::Surface.new 作为应该分配给 @image 的值。不幸的是,在我设置@rect 的下一行,它会抛出一个NoMethodError,因为@imagenil

@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 运行按预期工作,所以我很确定“或”语句的格式正确,但我无法弄清楚为什么它没有返回新的 Surface,而其他一切都是

【问题讨论】:

标签: ruby rubygame


【解决方案1】:

Ruby 中的orand 关键字具有非常非常低的优先级。甚至低于赋值运算符=。因此,只需分别用||&& 替换它们(两者的绑定都比= 更紧密),它应该可以按预期工作。 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]

【讨论】:

  • 运算符优先级是我的版本中的问题,但我尝试使用您的案例版本,但仍然返回 nil。方法参数满足第一个 when 条件 (image = Rubygame::Surface.new([640, 480])),但是如果你在 case 语句中省略参数,它与什么比较?
  • 这里使用case的方式,不带参数,只是测试when之后的每个表达式的真实性。当它找到第一个真值时它会停止。在我给出的示例中,将nil 分配给@image 的唯一方法是,如果Rubygame::Surface.autoloadRubygame::Surface.new 在特定情况下返回nil
【解决方案2】:

您是否尝试过更多级别的括号?

@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]))

【讨论】:

  • 在任何 Ruby 情况下都可以尝试使用这些和/或。这已经解决了我 90% 的条件问题。
  • 我只记得在 Perl 中 or 的优先级低于 ||=。写的代码充斥着括号,直到我弄明白为止。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 2020-03-18
    • 2012-06-14
    • 2014-11-15
    • 1970-01-01
    相关资源
    最近更新 更多