简单的“或”没有按预期工作

发布于 2024-09-18 21:28:48 字数 647 浏览 5 评论 0原文

我在下面相对简单的作业中遇到了一个有趣的问题。开头的每个括号内的块的计算结果均为 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 工作,所以我很确定“or”语句的格式良好,但我无法弄清楚为什么当其他一切都为 nil 时它不返回新的 Surface /em>。

I'm running into an interesting issue with the relatively simple assignment below. Each of the parenthesized chunks in the beginning evaluate to nil, leaving Rubygame::Surface.new as the value that @image ought to be assigned to. Unfortunately on the next line where I set @rect, it throws a NoMethodError because @image is nil.

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

Similar tests run through IRB work as expected, so I'm pretty sure the 'or' statement is well-formed, but I can't figure out why it isn't returning the new Surface when everything else is nil.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

标点 2024-09-25 21:28:49

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

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

Have you tried further levels of parentheses?

@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]))
眼波传意 2024-09-25 21:28:49

你为什么使用 RubyGame?用于 Ruby 的 Gosu 游戏开发框架更快、更流行。

Why are you using RubyGame? The Gosu game development framework for Ruby is faster and more popular.

被你宠の有点坏 2024-09-25 21:28:48

Ruby 中的 orand 关键字的优先级非常非常低。甚至低于赋值运算符=。因此,只需分别将它们替换为 ||&& (两者绑定都比 = 更紧密),它应该按您的预期工作。此处列出了 Ruby 的运算符优先级

除此之外,我想说你的代码非常密集。考虑将其重构为如下所示,我认为这可以更好地传达代码的意图。

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

The or and and keywords in Ruby have very, very low precedence. Even lower than the assignment operator =. So simply replace them with || and && respectively (both binding tighter than =), and it should work as you expect. Ruby's operator precedence is listed here.

In addition to that, I would say your code is very dense. Consider refactoring it to something like the following, which I think conveys the intent of your code much better.

@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]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文