Троїсний оператор Ruby без іншого


79

Чи існує рубінова ідіома для "If do-this" і "do-this" просто як проста команда?

наприклад, я зараз роблю

object.method ? a.action : nil

залишити речення else порожнім, але я відчуваю, що, мабуть, існує більш ідіоматичний спосіб зробити це, який не передбачає необхідності вказувати нуль в кінці. (і, як альтернатива, я вважаю, що зайняти кілька рядків коду було б марнотратно в цьому випадку.


Це залежить від контексту, але іноді елегантніше читати блок if / while / begin лише одним рядком у тілі, ніж щось більш щільне / стисле.
glenn jackman

Відповіді:



139

Як загальне правило: вам майже ніколи не потрібен тернарний оператор у Ruby. Причина, по якій він вам потрібен в C, полягає в тому, що в C if- це твердження, тому, якщо ви хочете повернути значення, вам доведеться використовувати тернарний оператор, який є виразом.

В Ruby, весь цей вислів є НЕ які - або заяви, що робить потрійний оператор досить багато зайвого. Ви завжди можете замінити

cond ? then_branch : else_branch

з

if cond then then_branch else else_branch end

Отже, у вашому прикладі:

object.method ? a.action : nil

еквівалентно

if object.method then a.action end

що, як зазначає @Greg Campbell, у свою чергу еквівалентно завершальній ifформі модифікатора

a.action if object.method

Крім того, оскільки булеві оператори в Ruby не просто повертають trueабо false, а значення останнього обчислюваного виразу, ви можете використовувати їх для керування потоком. Це ідіома, імпортована з Perl, і виглядатиме так:

object.method and a.action

7
тернарний оператор cond ? a : bкоротший за if cond then a else b end, що лише одне змушує мене використовувати його, щоб заощадити 11 символів ;-)
Маркус

1
Посібник із стилю Ruby стверджує: "Надавайте перевагу тернарному оператору ( ?:) перед if/then/else/endконструкціями. Це більш поширене і очевидно більш стисле".
Курт Бурбакі

18

Відповідь Грега є найкращою, але для запису, і навіть більше, ніж у C, вирази та твердження еквівалентні в Ruby, тому крім цього a.action if o.m?ви також можете робити такі речі:

object.method? && a.action

Ви можете писати (a; b; c) if dабо навіть

(a
 b
 c
) if d

або з цього приводу: (x; y; z) ? (a; b c) : (d; e; f)

У Рубі немає ситуації, коли дозволяється лише одне твердження або вираз ...


3

result = (<expression> && <true value>) || <false value>

value = 1 result = (value == 1 && 'one' ) || 'two' result #=> 'one' Поясніть: value == 1 && 'one' # => повертає результат останнього виразу, значення дорівнює 1, тому розділ буде обчислено та поверне 'one'.

value = 0 result = (value == 1 && 'one' ) || 'two' result #=> 'two'

Поясніть: значення! = 1 і вираз "і" не буде обчислюватися, але буде використано вираз instad "або", і він поверне "два"


1

Інший спосіб, як це можна зробити в тому ж рядку:

if object.method; a.action end

Це вважається Rubocop поганим стилем, оскільки він використовує крапку з комою для закінчення виразу, але я вважаю, що це є більш читабельним в деяких умовах, ніж прив'язка до оператора if в кінці. Легше пропустити оператор if наприкінці, і я не завжди хочу повертати щось, якщо умова не відповідає дійсності (як вас змушують використовувати тернарний оператор).

Ви також можете бути трохи більш багатослівним та прихильним до рубокопів:

if object.method then a.action end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.