RAII

Objective: Allocate resources and call given code in context of those resources. Finally clean-up resources despite of the fact if the code signalled an error or not.

Note: In the examples below 123 represents allocated resources.

Python

class Connection:
    def __init__(self, address):
        self.address = address
    
    def __enter__(self):
        print(f"Connection open to {self.address}")
        return 123
    
    def __exit__(self, ex_type, ex_val, ex_tb):
        print("Connection closed")
    
with Connection("target") as conn:
    print("Doing something well")
    
with Connection("target") as conn:
    raise Exception("Doing something wrong")

Alternatively:

from contextlib import contextmanager
    
@contextmanager
def Connection(address):
    print(f"Connection open to {address}")
    try:
        yield 123
    finally:
        print("Connection closed")

with Connection("target") as conn:
    print("Doing something well")
    
with Connection("target") as conn:
    raise Exception("Doing something wrong")

Rust

fn connection<F: FnOnce(i32) -> ()> (address: String, f: F ) {
    println!("Connection open to {}", address);
    f(123);
    println!("Connection closed");
}


fn main() {

  connection("target".to_string(), |_conn|{
      println!("Doing something well");
  });

  connection("target".to_string(), |_conn|{
      println!("Doing something wrong");
  });
  
  connection("target".to_string(), |_conn|{
      println!("Doing something miserably wrong");
      panic!("Boo"); // connection not closed
  });
  
}

Note: doesn't meet objectives in case of a panic. However many applications are made sure that they never panic.

Crystal

def connection(address)
  puts "Connection open to #{address}"
  begin
    yield 123
  ensure
    puts "Connection closed"
  end
end

connection("target") do |conn|
  puts "Doing something well"
end

connection("target") do |conn|
  raise "Doing something wrong"
end