Defer in Ada
Ada doesn’t have a direct equivalent to Go’s defer
keyword. However, we can achieve similar functionality using Ada’s exception handling mechanism and the finalization
concept. Here’s how we can implement a similar behavior:
with Ada.Text_IO;
with Ada.Exceptions;
with Ada.IO_Exceptions;
procedure Defer_Example is
type File_Type is limited private;
procedure Create_File (F : in out File_Type; Name : String);
procedure Close_File (F : in out File_Type);
procedure Write_File (F : in out File_Type);
procedure Create_File (F : in out File_Type; Name : String) is
begin
Ada.Text_IO.Put_Line ("creating");
Ada.Text_IO.Create (F, Ada.Text_IO.Out_File, Name);
exception
when others =>
raise Ada.IO_Exceptions.Name_Error with "Could not create file";
end Create_File;
procedure Write_File (F : in out File_Type) is
begin
Ada.Text_IO.Put_Line ("writing");
Ada.Text_IO.Put_Line (F, "data");
end Write_File;
procedure Close_File (F : in out File_Type) is
begin
Ada.Text_IO.Put_Line ("closing");
Ada.Text_IO.Close (F);
exception
when others =>
Ada.Text_IO.Put_Line (Ada.Text_IO.Standard_Error, "Error closing file");
Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Failure);
end Close_File;
F : File_Type;
begin
Create_File (F, "/tmp/defer.txt");
begin
Write_File (F);
exception
when others =>
Close_File (F);
raise;
end;
Close_File (F);
exception
when E : others =>
Ada.Text_IO.Put_Line (Ada.Text_IO.Standard_Error,
"Unexpected error: " & Ada.Exceptions.Exception_Message (E));
Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Failure);
end Defer_Example;
In this Ada example, we’ve implemented functionality similar to Go’s defer
using Ada’s exception handling mechanism. Here’s how it works:
We define a
File_Type
and procedures to create, write to, and close a file.In the main procedure, we create the file and then use a nested block to write to it.
If an exception occurs during file writing, we ensure the file is closed in the exception handler before re-raising the exception.
If no exception occurs, we close the file after writing.
We’ve wrapped the entire main procedure in an exception handler to catch any unexpected errors.
This approach ensures that the file is always closed, whether an exception occurs or not, similar to how Go’s defer
works.
To run the program:
$ gnatmake defer_example.adb
$ ./defer_example
creating
writing
closing
This Ada implementation provides similar functionality to the Go example, ensuring proper resource cleanup even in the face of exceptions.