2016-06-15 8 views
4

Я новичок в Ruby, и я работаю над проектом, который включает в себя использование этого. Go предлагает оператор defer, и я хотел бы знать, как я мог бы реплицировать эту функцию в ruby.Что такое рубиновый эквивалент Go defer?

Пример:

dst, err := os.Create(dstName) 
if err != nil { 
    return 
} 
defer dst.Close() 

ответ

8

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

В блоке

begin 
    # ... 
ensure 
    # This code will be executed even if an exception is thrown 
end 

В способе

def foo 
    # ... 
ensure 
    # ... 
end 

Object#ensure Marks окончательная, необязательное предложение о начать конец блока /, как правило, в тех случаях, когда блок также содержит предложение о спасении. Код гарантии в условии обеспечения гарантированно будет выполнен, независимо от того, идет ли управление потоками на аварийный блок или нет.

0

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

module Deferable 
    def defer &block 
    @defered_methods << block 
    end 

    def self.included(mod) 
    mod.extend ClassMethods 
    end 

    module ClassMethods 
    def deferable method 
     original_method = instance_method(method) 
     define_method(method) do |*args| 
     @@defered_method_stack ||= [] 
     @@defered_method_stack << @defered_methods 
     @defered_methods = [] 
     begin 
      original_method.bind(self).(*args) 
     ensure 
      @defered_methods.each {|m| m.call } 
      @defered_methods = @@defered_method_stack.pop 
     end 
     end 
    end 
    end 
end 

class Test 
    include Deferable 

    def test 
    defer { puts "world" } 
    puts "hello" 
    end 

    def stacked_methods str 
    defer { puts "and not broken" } 
    defer { puts "at all" } 
    puts str 
    test 
    end 

    def throw_exception 
    defer { puts "will be executed even if exception is thrown" } 
    throw Exception.new 
    end 

    deferable :test 
    deferable :stacked_methods 
    deferable :throw_exception 
end 

Пример вызовов:

t = Test.new 
t.test 

# -> Output: 
# hello 
# world 

t.stacked_methods "stacked methods" 

# -> Output: 
# stacked methods 
# hello 
# world 
# and not broken 
# at all 

t.throw_exception 
# -> Output: 
# will be executed even if exception is thrown 
# deferable.rb:45:in `throw': uncaught throw #<Exception: Exception> (UncaughtThrowError) 
#   from deferable.rb:45:in `throw_exception' 
#   from deferable.rb:18:in `call' 
#   from deferable.rb:18:in `block in deferable' 
#   from deferable.rb:59:in `<main>' 
+0

Кто-то downvoted это. Зачем? Не работает ли этот код? Имеются ли уродливые последствия? Это выглядит законным и опрятным. – Narfanator

 Смежные вопросы

  • Нет связанных вопросов^_^