2016-06-15 6 views
4

私はRubyには新しく、これを使用するプロジェクトに取り組んでいます。 Goはdeferというステートメントを提供しています。私はその機能をどのようにルビーで再現できるのか知りたかったのです。Go deferのルビに相当するものは何ですか?

例:

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

答えて

8

何の適切な同等物は、特定のコードブロックが実行されたことを確認するただし場合、あなたはensureステートメントを使用することができ、ルビーでdeferステートメントにありません。違いは、deferのようなコードブロックをスタックすることはできませんが、結果は同じです。ブロック

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

方法において

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

Object#ensure

は、開始/終了ブロックの最終的な、オプションの句をマーク場合には、一般 ブロックにはレスキュー句も含まれています。 制御がレスキューブロックに流れるかどうかにかかわらず、確実に句内の コードが実行されることが保証されています。

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

関連する問題