Цепочка методов Ruby с блоками - сбивающая с толку несовместимая синтаксическая ошибка

Итак, думая, что я умный, я добавляю такой метод к Object:

class Object
  def apply_if(cond)
    if cond
      yield self
    else
      return self
    end
  end
end

Это (я думал) позволяет мне условно добавлять биты в цепочку методов, что немного упрощает манипуляции с запросами ActiveRecord. Но это дает синтаксическую ошибку, которую я могу сократить до следующего кода:

data = [1,2,3,4,5]
results = data.
  apply_if(true and false) do |q|
    q + [0,0]
  end

Точно так же эти ошибки:

results = data.apply_if(true and false){|q| q + [0,0]}

Но это работает:

results = data.apply_if ((true and false)) {|q| q + [0,0]}

Как делает:

results = data.apply_if (true && false) {|q| q + [0,0]}

Я вижу, что все различия связаны с приоритетом оператора, но какое значение может иметь приоритет оператора внутри пары круглых скобок?

Почему здесь вообще синтаксическая ошибка? Я не вижу вероятных синтаксических двусмысленностей, и этот метод идентичен по форме методу Array#reduce.

Здесь я пробовал несколько комбинаций — явные параметры блока с вызовами, различные типы явного приоритета внутри определения метода. Использование лямбды вместо блока работало нормально, но явно слишком неуклюже для моих целей.


person nevinera    schedule 14.10.2011    source источник
comment
Чувак, Эрик. Разве я не научил тебя лучшему? Этот код отчаянно нуждается в тернарном операторе! :)   -  person Stephen Touset    schedule 15.10.2011
comment
Я изначально (и, возможно, снова) написал его, чтобы также принимать процедуру в позиции условия (та, которая принимает объект в качестве своего параметра), что казалось самым чистым как условие с 3 ветвями. Я использую тернарии, я делаю!   -  person nevinera    schedule 17.10.2011


Ответы (1)


Это не имеет ничего общего с вашим кодом — оператор and просто не разрешен в списке аргументов. Что касается почему, вы должны спросить основную команду, но наиболее очевидная возможность, IMO, заключается в том, что его raison d'etre (имеющий чрезвычайно низкий приоритет) не работает в списке аргументов.

person Chuck    schedule 14.10.2011
comment
Интересно, как я раньше никогда не сталкивался с этим ограничением? Кажется, единственная проблема, спасибо :-) - person nevinera; 15.10.2011
comment
Я нашел тред на ruby-core на эту тему. См. комментарий matz и < href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/7560" rel="nofollow noreferrer">ответ на него. - person knut; 15.10.2011
comment
@knut: Спасибо за это. Должен любить, когда ваши дикие догадки на самом деле верны. - person Chuck; 15.10.2011
comment
Я все еще не привык думать о запятой как об операторе. Хотя теперь это имеет смысл; спасибо за ссылку на обсуждение! - person nevinera; 17.10.2011