Рубиновый троичный оператор - PullRequest
0 голосов
/ 09 марта 2011

Почему эти два утверждения не эквивалентны?

  1. defined? foo ? foo << "bar" : foo = ["bar"]
  2. if (defined? foo) then foo << "bar" else foo = ["bar"] end

Первое утверждение:

irb(main):001:0> defined? foo ? foo << "bar" : foo = ["bar"]
=> nil
irb(main):002:0> foo
=> nil
irb(main):003:0> defined? foo ? foo << "bar" : foo = ["bar"]
=> "expression"
irb(main):004:0> foo
=> ["bar"]

Второе утверждение:

irb(main):001:0> if (defined? foo) then foo << "bar" else foo = ["bar"] end
=> ["bar"]
irb(main):002:0> foo
=> ["bar"]
irb(main):003:0> if (defined? foo) then foo << "bar" else foo = ["bar"] end
=> ["bar", "bar"]
irb(main):004:0> foo
=> ["bar", "bar"]

Эти сеансы с JRuby 1.5.0 (должны быть эквивалентны нативному Ruby 1.8.7). Я вижу немного другое поведение с родным ruby ​​1.9.1: оператор # 1 никогда не определяет foo даже при его двойном запуске.

Ответы [ 2 ]

5 голосов
/ 09 марта 2011

Потому что первый оценивает:

defined?(foo ? foo << "bar" : foo = ["bar"])

Почему это возвращает ноль, я понятия не имею ...

Исправление просто сделать:

(defined? foo) ? foo << "bar" : foo = ["bar"]
1 голос
/ 09 марта 2011
  1. определяется? фу? foo << "bar": foo = ["bar"] </li>
  2. если (определено? Foo), то foo << "bar" иначе foo = ["bar"] end </li>

В любом случае ваш код может быть упрощен. Основываясь на двух приведенных выше примерах, похоже, что будет какой-то замкнутый цикл. Вместо того, чтобы пытаться создать foo внутри него и инициализировать первый ['bar'], я бы сделал что-то вроде:

foo = []
... start some loop ...
  foo << bar
... end some loop ...

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

(foo ||= []) << "bar"

Этот второй способ немного "Perlish", но он не так уж далек от Ruby-пути, чтобы его невозможно было расшифровать.

...