#ruby
#ruby
Вопрос:
Что означает @ в следующем коде Ruby:
module TestRocket
extend Module.new { attr_accessor :out }
def _test(a, b); send((call rescue()) ? a : b); end
def @; _show _test :_pass, :_fail end
def -@; _show _test :_fail, :_pass end
def ~@; _show _pend; end
def !@; _show _desc; end
def _show(r); (TestRocket.out || $>) << r; r end
def _pass; " OKn"; end
def _fail; " FAIL @ #{source_location * ':'}n"; end
def _pend; "PENDING '#{call}' @ #{source_location * ':'}n"; end
def _desc; " FIRE '#{call}'!n"; end
end
Proc.send :include, TestRocket
Затем это используется как:
-> { Die.new(2) }
--> { raise }
-> { 2 2 == 4 }
Как @ превращается в ‘->’ в имени функции?
Комментарии:
1. хороший вопрос. Я никогда этого не видел. Но если вы попытаетесь запустить
-> { 2 2==4 }
без него, вы получите ошибкуNoMethodError: undefined method
@’ для #<Proc:0x0000010>`. Итак, я предполагаю, что это волшебный метод из ruby 1.92. Репозиторий TestRocket является github.com/peterc/testrocket
Ответ №1:
Имена методов для четырех унарных операторов
, -
, ~
и !
являются @
, -@
, ~@
и !@
. Итак, забавно выглядящие определения методов:
def @; _show _test :_pass, :_fail end
def -@; _show _test :_fail, :_pass end
def ~@; _show _pend; end
def !@; _show _desc; end
просто определите перегрузки для этих четырех унарных операторов. Затем TestRocket исправляется в классе Proc с помощью Proc.send :include, TestRocket
.
Это:
-> { Die.new(2) }
это просто определение лямбды и другой способ записи lambda { Die.new(2) }
. Затем, с помощью TestRocket, исправленного в Proc, мы можем сказать это:
-> { Die.new(2) }
# lambda { Die.new(2) }
и он будет запускать этот метод:
def @; _show _test :_pass, :_fail end
в качестве метода экземпляра для этого лямбда.
Похоже на злоупотребление перегрузкой унарного оператора, чтобы «изобрести» что-то похожее на новые операторы -->
, ~->
, ….