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
end
In 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
main
function opens a file, writes to it, and ensures it’s closed.create_file
opens a file for writing and returns the file handle. If there’s an error, it raises an exception.write_file
writes data to the file.close_file
closes 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
closing
This 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.