Defer in Elixir
In Elixir, we don’t have a direct equivalent to the defer keyword. However, we can achieve similar functionality using the try, rescue, and after constructs. Here’s how we can implement the same behavior:
defmodule DeferExample do
def main do
{:ok, file} = create_file("/tmp/defer.txt")
try do
write_file(file)
after
close_file(file)
end
end
defp create_file(path) do
IO.puts("creating")
case File.open(path, [:write]) do
{:ok, file} -> {:ok, file}
{:error, reason} -> raise "Failed to create file: #{reason}"
end
end
defp write_file(file) do
IO.puts("writing")
IO.write(file, "data\n")
end
defp close_file(file) do
IO.puts("closing")
case File.close(file) do
:ok -> :ok
{:error, reason} ->
IO.puts(:stderr, "error: #{reason}")
System.halt(1)
end
end
endIn this Elixir version, we use a try block to ensure that the file is closed after writing, regardless of whether an exception occurs or not. The after clause in the try block serves a similar purpose to defer in the original example.
Let’s break down the main parts:
The
mainfunction opens a file, writes to it, and ensures it’s closed.create_fileopens a file for writing and returns the file handle. If there’s an error, it raises an exception.write_filewrites data to the file.close_filecloses the file and checks for errors. If there’s an error during closing, it prints the error and exits the program.
To run this program:
$ elixir defer_example.exs
creating
writing
closingThis Elixir implementation demonstrates how to ensure that certain operations (like closing a file) are performed, even if exceptions occur during the execution of the main logic. While it’s not exactly the same as Go’s defer, it achieves a similar result in terms of resource management and cleanup.