【问题标题】:Why do I get a syntax error using the ternary operator?为什么使用三元运算符会出现语法错误?
【发布时间】:2013-11-09 08:19:57
【问题描述】:

我编写了一个 if-then-else 程序,但是在更改代码以使用三元运算符时,我遇到了语法错误,无法弄清楚为什么它不起作用:

def are_you_over_21
  puts"How old are you?"
  age = gets.chomp.to_i
  age>=21 ? puts"You're over 21!" : puts"You're too young."
end

are_you_over_21

【问题讨论】:

  • 确切的语法错误是什么? Ruby 会告诉你是哪一行生成它,并且知道这有助于我们帮助你。

标签: ruby ternary-operator


【解决方案1】:

试试这个:

age>=21 ? puts("You're over 21!") : puts("You're too young.")

当给定的选项有没有括号的函数调用时,三元运算符会感到困惑。

您也可以这样做:

puts age>=21 ? "You're over 21!" : "You're too young."

【讨论】:

    【解决方案2】:

    您必须考虑 Ruby 解析器。

    这样可以正常工作:

    age >= 21 ? puts("You're over 21!") : puts("You're too young.")
    

    原因是如果使用不带括号的puts方法,解析器无法理解后面出现的:标记;它没有意识到它之前与三元运算符相关联。你也可以这样做:

    puts age >= 21 ? "You're over 21!" : "You're too young."
    

    这很好——解析器不会在这里遇到任何歧义。

    你也可以这样做:

    puts "You're #{ age >= 21 ? 'over 21!' : 'too young.' }"
    

    这就是产生歧义的原因。假设您有两个函数,x 和 a,如下所示:

    2.0.0-p195 :033 > def x(y)
    2.0.0-p195 :034?>   y + 1
    2.0.0-p195 :035?>   end
     => nil 
    2.0.0-p195 :036 > def a(b)
    2.0.0-p195 :037?>   b + 2
    2.0.0-p195 :038?>   end
     => nil 
    

    括号在这里没有区别:

    2.0.0-p195 :039 > x a 1
     => 4 
    2.0.0-p195 :040 > x a(1)
     => 4 
    2.0.0-p195 :041 > x(a(1))
     => 4 
    2.0.0-p195 :042 > x(a 1)
     => 4 
    

    但是如果x 可以接受多个参数呢?现在你必须帮助解析器:

    2.0.0-p195 :043 > def x(y, z)
    2.0.0-p195 :044?>   y + z + 1
    2.0.0-p195 :045?>   end
    

    让我们像以前一样不带括号拨打电话:

    2.0.0-p195 :047 > x a 1, 2 
    

    您是将a(1), 2 传递给x,还是尝试调用a(1, 2) 并将结果传递给x?按照惯例,Ruby 假定您正在尝试调用 a(1, 2),但 a 只接受一个参数,因此您会收到错误:

    ArgumentError: wrong number of arguments (2 for 1)
      from (irb):36:in `a'
    

    所以你需要括号:

    2.0.0-p195 :052 > x a(1), 2
     => 6 
    

    【讨论】:

    • 这是一个很好的回应,对于希望了解一些 Ruby 内部原理的新手来说也是一个 irb/mri gem。
    【解决方案3】:

    比在三元中做无条件的puts,这是一个条件语句,为什么不是三元的结果puts?

    def are_you_over_21                                
      puts"How old are you?"                           
      age = gets.to_i                                  
      age >= 21 ? "You're over 21!" : "You're too young."
    end                                                
    
    puts are_you_over_21 
    

    此外,这不是错误,但数字的性质(在您的情况下为整数)意味着它永远不需要chomp,因为数字没有换行符。你永远不需要使用chomp.to_i 或chomp.to_f。

    请注意,该方法现在返回 String 的实例,而不是 nil。现在可以随心所欲地使用它,在这种情况下,使用puts 显示到终端。

    比较运算符周围的空格使其更易于阅读。

    如果要提示、获取数据和报告,方法本身也可能不是方法。您也可以删除方法定义并将其作为运行代码。

    我已将其重构为这样:

    def are_you_over_21(age)
      age >= 21 ? "You're over 21!" : "You're too young."
    end
    
    [18, 20, 21, 22, 100].each do |age|
      puts are_you_over_21(age)
    end
    
    # >> You're too young.
    # >> You're too young.
    # >> You're over 21!
    # >> You're over 21!
    # >> You're over 21!
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-13
      • 2012-11-19
      • 1970-01-01
      • 2020-02-29
      • 2012-10-01
      • 2022-01-11
      • 2018-06-10
      • 2017-05-15
      相关资源
      最近更新 更多