问题描述
是否可以通过GNAT来确保所有异常情况都得到处理?
举个例子:
package IO renames Ada.Text_IO;
package EIO renames Ada.IO_Exceptions;
procedure Open_File (File : in out IO.File_Type) is
begin
IO.Open (File,IO.In_File,"example.txt");
exception
when EIO.Use_Error =>
IO.Put_Line ("Use!");
when EIO.Device_Error =>
IO.Put_Line ("Device!");
end Open_File;
Open
也可以提出Name_Error
,因此我希望GNAT警告该案件尚未得到处理。
我发现了pragma Restrictions (No_Exception_Propagation)
,但这似乎也将检查应用于标准库调用,因此Open
变得不可用,因为它本身会传播异常。如果将其应用于示例,则会得到:
14:07: warning: pragma Restrictions (No_Exception_Propagation) in effect
14:07: warning: this handler can never be entered,and has been removed
16:07: warning: pragma Restrictions (No_Exception_Propagation) in effect
16:07: warning: this handler can never be entered,and has been removed
例如,我想从另一种语言获得的内容; Nim具有raises
杂注以注释过程可引发的异常,编译器将其强制执行。该列表可以为空,即。 raises: []
,并且编译器将要求所有异常都将被处理且不会传播。在Ada中有与此等效的东西吗?
解决方法
如果要处理所有可用的异常,可以在when others
部分中使用exception
。您的示例将如下所示:
package IO renames Ada.Text_IO;
package EIO renames Ada.IO_Exceptions;
procedure Open_File (File : in out IO.File_Type) is
begin
IO.Open (File,IO.In_File,"example.txt");
exception
when An_Exception : others =>
IO.Put_Line (EIO.Exception_Message(An_Exception));
end Open_File;
如果要以单独的方式处理每个异常,则必须分别列出每个异常(如您的示例所示)。但是编译器不会警告您有关缺少异常处理程序的信息。
,在Ada中是不可能的。
Nim之所以能够做到这一点,是因为class TicketComment < ApplicationRecord
after_save :extract_mentions
after_commit :notify
def extract_mentions
current_mentions = mentions.map(&:user).map(&:username)
new_mentions = description.scan(/(?<=^|(?<=[^a-zA-ZÀ-ž0-9_-]))@([a-zA-ZÀ-ž]+[a-zA-ZÀ-ž0-9_]+)/).flatten
mentions_to_add = new_mentions - current_mentions
mentions_to_remove = current_mentions - new_mentions
users_to_add = User.select(:id).where("username IN (?)",mentions_to_add.flatten).map(&:id)
users_to_remove = User.select(:id).where("username IN (?)",mentions_to_remove.flatten).map(&:id)
users_to_add&.each do |id_to_add|
mentions.create(user_id: id_to_add)
end
mentions.where(user_id: users_to_remove).destroy_all
end
def notify
user_ids = ticket.participants.pluck(:id) - [Current.user.id]
TicketCommentMailer.comment_added(id,user_ids).deliver_later
end
end
编译指示是函数签名的一部分。因此,对于任何调用,静态地知道可以引发哪些异常。在Ada中不是这种情况。
如果您认为编译器可以隐式找出任何子例程可以引发哪些异常,那是对的,但不能解决问题,因为Ada允许分派调用和函数指针。对于这两种方法,您都不知道将被静态调用的函数(无论如何都没有指针分析,对于大多数编译器而言,这是超出范围的),因此无法知道可能引发的异常(因为它们不是一部分)签名。)