Как использовать условный оператор (? :) в Ruby? - PullRequest
285 голосов
/ 23 ноября 2010

Как условный оператор (? :) используется в Ruby?

Например, это правильно?

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>

Ответы [ 6 ]

467 голосов
/ 23 ноября 2010

Это троичный оператор , и он работает как в C (круглые скобки не требуются).Это выражение работает так:

if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this

Однако в Ruby if также является выражением так: if a then b else c end === a ? b : c, за исключением проблем с приоритетами.Оба являются выражениями.

Примеры:

puts (if 1 then 2 else 3 end) # => 2

puts 1 ? 2 : 3                # => 2

x = if 1 then 2 else 3 end
puts x                        # => 2

Обратите внимание, что в первом случае требуются круглые скобки (в противном случае Ruby сбивается с толку, поскольку думает, что это puts if 1 с дополнительным мусором после него), но они не требуются в последнем случае, поскольку упомянутая проблема не возникает.

Вы можете использовать форму "long-if" для удобства чтения на нескольких строках:

question = if question.size > 20 then
  question.slice(0, 20) + "..."
else 
  question
end
32 голосов
/ 23 ноября 2010
puts true ? "true" : "false"
=> "true"


puts false ? "true" : "false"
=> "false"
25 голосов
/ 23 ноября 2010

Использование вами ERB предполагает, что вы находитесь в Rails. Если это так, то рассмотрим truncate, встроенного помощника, который сделает всю работу за вас:

<% question = truncate(question, :length=>30) %>
17 голосов
/ 23 ноября 2010

@ pst дал отличный ответ, но я хотел бы отметить, что в Ruby троичный оператор записан в одну строку, чтобы быть синтаксически правильным, в отличие от Perl и C, где мы можем записать его в несколько строк:

(true) ? 1 : 0

Обычно Ruby выдает ошибку, если вы пытаетесь разбить ее на несколько строк, но вы можете использовать символ продолжения строки \ в конце строки, и Ruby будет счастлив:

(true)   \
  ? 1    \
  : 0

Это простой пример, но он может быть очень полезен при работе с более длинными строками, так как он хорошо сохраняет код.

Также возможно использовать троичный без символов продолжения строки с помощьюставить операторы в последнюю очередь, но я не люблю или не рекомендую это:

(true) ?
  1 :
  0

Я думаю, что это приводит к действительно трудному чтению кода, поскольку условный тест и / или результаты становятся длиннее.

Я читал комментарии о том, что не следует использовать троичный оператор, потому что это сбивает с толку, но это плохая причина не использовать что-то.По той же логике мы не должны использовать регулярные выражения, операторы диапазона ('..' и, казалось бы, неизвестный вариант "триггера").Они эффективны при правильном использовании, поэтому мы должны научиться правильно их использовать.


Почему вы поставили скобки вокруг true?

РассмотримПример OP:

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>

Упаковка условного теста помогает сделать его более читабельным, поскольку он визуально разделяет тест:

<% question = (question.size > 20) ? question.question.slice(0, 20)+"..." : question.question %>

Конечно, весь пример можно сделать намного более читабельнымиспользуя некоторые разумные дополнения пробелов.Это не проверено, но вы поймете, что идея:

<% question = (question.size > 20) ? question.question.slice(0, 20) + "..." \
                                   : question.question 
%>

Или, более подробно написано более идиоматически:

<% question = if (question.size > 20)
                question.question.slice(0, 20) + "..."
              else 
                question.question 
              end
%>

Было бы легко утверждать, что читаемость сильно страдает от question.question тоже.

3 голосов
/ 29 мая 2016

Простой пример, когда оператор проверяет, равен ли идентификатор игрока 1, и устанавливает идентификатор врага в зависимости от результата

player_id=1
....
player_id==1? enemy_id=2 : enemy_id=1
# => enemy=2

И я нашел сообщение о теме, которое кажется довольно полезным.

0 голосов
/ 18 сентября 2018

Код condition ? statement_A : statement_B эквивалентен

if condition == true
  statement_A
else
  statement_B
end
...