Search code examples
crystal-lang

Scope variables/guards


Is it possible to have a variable that is guaranteed to be finalized on the scope exit.

Specifically, I want a guard: something that calls a specific function on initialization, and calls another specific function on scope exit.


Solution

  • This is best done explicitly:

    class Guard
      def initialize
        # Init things here
      end
    
      def close
        # clean up things here
      end
    end
    
    def my_method
      guard = Guard.new
      # do things here
    ensure
      guard.close
    end
    

    Then a common pattern is to provide a nicer interface using a yielding method. You'll notice you see this a lot in the standard library when working with external resources:

    class Guard
      def self.obtain
        guard = new
        yield guard
      ensure
        guard.close
      end
    
      # ...
    end
    
    Guard.obtain do |guard|
      # do things
    end
    

    Of course yielding the actual resource object is optional if the consumer should never interact with it.