【问题标题】:Does it matter if a conditional statement comes before or after the expression?条件语句出现在表达式之前还是之后有关系吗?
【发布时间】:2011-05-28 21:09:38
【问题描述】:

对不起,如果这是一个愚蠢的问题,但我是一个 C# 家伙,在 ruby​​ 上摸索着。

在 ruby​​ 中,我注意到很多人这样做:

do_something(with params) if 1 = 1

这和这个有什么区别(甚至是细微的):

if 1 = 1 do_something(with params)

还是为了更清晰而写的相同?

【问题讨论】:

  • 主要是风格。在处理单行代码时,我使用尾随条件,因为它似乎在对话中更有意义。由于编写软件的很大一部分是使其可维护,因此我尝试以一种允许它轻松滑入大脑的方式编写它。有些书建议只使用块或包装条件if (blah) ... some code ... end,认为这对将来的代码扩展更好。如果我们需要添加一些东西,关闭 end 已经存在。我发现我的 vim 能力很容易解决这个问题,所以我主要使用单行。

标签: ruby syntax if-statement conditional


【解决方案1】:

后者在语法上无效。你需要写:

if 1==1 then do_something(with params) end

单行条件句必须始终尾随。 是的,有区别。试试这些:

bar1 = if foo1=14
  foo1*3
end
#=> 42

bar2 = foo2*3 if foo2=14
#=> NameError: undefined local variable or method `foo2' for main:Object

在后者中,Ruby 在引用之后看到赋值,因此将foo2 视为方法而不是局部变量。仅在以下情况下才会出现问题:

  • 您有意在条件中使用赋值(不是测试相等性),并且
  • 这是第一次(就源顺序而言)此变量在作用域中被分配。

【讨论】:

  • warning: found = in conditional, should be ==
  • @JonasElfström 是的,还有那个。但问题仍然存在。在 Ruby 中,在条件句中使用赋值是很常见的(我个人和其他代码)。 if user=User.find(42) then ... end。遗憾的是,当赋值是单行尾随条件时,局部变量的启发式方法不起作用。
  • @Phrogz,我试图了解为什么尾随条件中的分配失败。我在哪里可以了解更多信息?
  • @Leito 问题在于 Ruby 的解释器使用启发式方法来确定一个未限定的、未经修饰的名称是局部变量还是方法调用,因为对于 foo = barbar 可能是一个局部变量或不带参数的方法调用。据我了解,启发式方法是基于名称在源代码中第一次在词法上出现时的使用方式。在有问题的情况下,它决定foo2 是一个方法调用而不是一个局部变量,并且从那时起就假定它是这样的。
  • @Leito 例如,这个可怕的 hack 让它再次工作:bar = (foo||=0) && (foo*3) if foo=14 因为现在它第一次看到foo 它知道它必须是一个局部变量而不是一个方法调用。或者,只需将foo=nil 放在行前也可以修复它。
【解决方案2】:

它是语法糖...让我们以更易于阅读的方式编写代码。

http://rubylearning.com/satishtalim/ruby_syntactic_sugar.html

注意:对于@Phrogz,以下内容不一样! 请确保您没有尝试将值分配给变量,而不是将变量与值进行比较!此外,正如 Phrogz 所提到的,变量赋值的顺序有很大的不同......有关更多详细信息,请参阅@Phrogz 答案!

if 1 = 1 then do_something(with params) end
if 1 == 1 then do_something(with params) end

【讨论】:

    【解决方案3】:

    启动irb 并运行您的代码,您将学习:

    • 1=1 是语法错误,改为 1==1。
    • 您不能在if 1==1 之后直接使用表达式,您必须添加:then 并以end 结束。

    结尾的if 应该只用于单个表达式,并且不能添加else。它们被称为语句修饰符,它们只是语法糖以提高可读性。我并不完全反对它们,但建议谨慎使用它们。

    【讨论】:

      【解决方案4】:

      您可以使用其中任何一种,但如果您将 if 语句放在首位,那么您将需要使用“结束”来关闭条件。

      if 1==1 
         do_something(with params)
      end
      

      【讨论】:

        【解决方案5】:

        以下将 foo 设为 nil。

        foo = true unless defined?(foo) #Leaves foo as nil
        

        这是因为 Ruby 创建了一个变量 foo 并在读取(我认为是解析)foo = true 位时将其分配给 nil,然后当它读取(我认为是执行)unless defined?(foo) 时,它表示 foo 已定义(定义为 nil),因此不执行 foo = true 部分。

        如果你这样做了

        unless defined?(foo)
          foo = true
        end
        

        那么你会得到 foo 为真。

        我将此添加到What are the Ruby Gotchas a newbie should be warned about?,因为有人对此感到困惑here

        所以是的,在某些情况下它可能很重要。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-16
          • 1970-01-01
          • 1970-01-01
          • 2015-10-22
          • 2021-02-15
          • 2014-07-30
          相关资源
          最近更新 更多