【问题标题】:Is there a way to make this Ruby ternary operation evaluate properly?有没有办法让这个 Ruby 三元运算正确评估?
【发布时间】:2012-06-28 10:06:18
【问题描述】:

以下代码行

<% invite.accepted ? { @going, @not_going = 'selected', '' } : { @going, @not_going = '', 'selected' } %>

是我尝试将几个操作(评估一个表达式并相应地设置两个变量的值)压缩成一行。

它引发了一个错误,声称有一个意外的逗号。

有没有办法让这个工作,或者我只是重载了可怜的三元运算符?

(顺便说一句,这只是一个个人实验。我不介意使用简单的 -- 尽管很麻烦 -- if/else 语句)

编辑:以下代码行有效!我会尽快核对正确答案!

<% invite.accepted ? ( @going, @not_going = 'selected', '' ) : ( @going, @not_going = '', 'selected' ) %>

【问题讨论】:

    标签: ruby ternary-operator


    【解决方案1】:

    您似乎将true 分配给invite.accepted 而不是对其进行测试,试试这个:

    <% (invite.accepted == true) ? (@coming, @not_coming = 'coming', '') : (@going, @not_going = 'not coming', 'selected') %>
    

    这样会更好,因为您不需要测试 true == true:

    <% (invite.accepted) ? (@coming, @not_coming = 'coming', '') : (@going, @not_going = 'not coming', 'selected') %>
    

    编辑

    您也可以尝试将其包装在一个函数中,以便它评估为单个实体:

    <% (invite.accepted) ? assign(@coming, @not_coming, 'coming', '') : assign(@going, @not_going, 'not coming', 'selected') %>
    
    def assign(a,b,c,d)
       a, b = c,d;
    end
    

    【讨论】:

    • 如果是这样,它至少应该允许忽略块的@going.. 侧。我认为?: 不是为处理这种情况而设计的。
    • 试过了,但没有运气。不过谢谢!
    • 是的,萨诺德,我开始认为是这样。老实说,这没什么大不了的,只是好奇。
    • 我能想到的唯一其他建议是将所有内容都括在括号中。我从来没有见过这样的三元运算符。
    【解决方案2】:

    怎么样:

    @going, @not_going = invite.accepted ? ['selected', ''] : ['', 'selected']
    

    w, x = y, zw, x = [y, z] 是一样的,所以这样就可以了,没有重复。

    【讨论】:

    • 我不知道如何避免“紧凑”,但是 '@going, @not_going = ['selected', ''].send(invite.accepted ? :compact : :reverse )'
    • @oldergod,如果可以再多一行:tags = ['selected', '']; @going, @not_going = invite.accepted ? tags : tags.reverse
    【解决方案3】:

    Parens ; 工作:

    irb(main):018:0> foo = true ? (a=:a ; b=:b) : :foo
    => :b
    irb(main):019:0> a
    => :a
    irb(main):020:0> b
    => :b
    irb(main):021:0> 
    

    注意, 不是语句分隔符:

    irb(main):001:0> a=:a, b=:b
    => [:a, :b]
    irb(main):002:0> a
    => [:a, :b]
    irb(main):003:0> b
    => :b
    irb(main):004:0> 
    

    ; 是语句分隔符:

    irb(main):004:0> a=:a; b=:b
    => :b
    irb(main):005:0> a
    => :a
    irb(main):006:0> b
    => :b
    irb(main):007:0> 
    

    但这并不能立即帮助您,因为解释器不是在寻找语句分隔符——只有::

    irb(main):014:0> foo = true ? a=:a, b=:b : :foo
    SyntaxError: (irb):14: syntax error, unexpected ',', expecting ':'
    foo = true ? a=:a, b=:b : :foo
    ...
    

    Parens 和 , 不会引发错误,但无法按预期工作:

    irb(main):021:0> foo = true ? (a=:a , b=:b) : :foo
    => [:a, :b]
    irb(main):022:0> a
    => [:a, :b]
    irb(main):023:0> b
    => :b
    irb(main):024:0> 
    

    我希望 do .. end 可以工作,但这也失败了:

    irb(main):024:0> foo = true ? do a=:a ; b=:b end : :foo
    SyntaxError: (irb):24: syntax error, unexpected keyword_do
    foo = true ? do a=:a ; b=:b end : :foo
    ...
    

    【讨论】:

    • 我正在阅读 OP 的示例,类似于 (a, b = :a, :b)。看起来 Ruby 也是如此。逗号不充当语句分隔符;它正在创建列表/元组/任何东西。
    • @cHao:啊!我根据the first version of the question 写了我的答案,看起来目标invite.accepted = (@going, @not_going='','')——将三个值存储到invite.accepted 中并在此过程中更新一个变量。您的解释 - 由较新的编辑证实 - 绝对更清晰。和Matheus has a superb solution 对问题的解释。 :)
    • 为什么不使用文字 a=1 and b=2 语句。我不太喜欢使用分号。
    • @Jason:我认为a=:a 会提高清晰度,并期望每个变量都有其符号作为其值。当变量没有相应的符号作为其值时,很容易发现它们是错误的。如果我删除了复杂的irb 提示符,也许它会感觉更少的标点符号......
    猜你喜欢
    • 2023-01-07
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多