0

我一直在为这个小问题苦苦挣扎一段时间。我正在尝试创建自己的内部 JSON 结构实现。挑战在于,对于 Ada,我必须使用访问类型来使其递归,如果我没有严格控制访问类型,访问类型就有泄漏的风险。为了控制它,我将我提供的所有真实活动保密,Get (Source:...)并且Set (Target:...; Value:...)Node 类型的函数/过程,它将尝试验证和处理任何现有的 Vector (json-array) 或 Map (json-object) 元素。为了进一步确保我使用 Ada 2012 的稳定功能并在内容超出范围时捕获它们,我尝试使用 Protected_Controlled 类型和“管理”Ada 库,但发现容器库无法处理受保护的类型,所以我简单地使用了受控。该Finalize (...)过程适用于任何 Vector 或 Map 类型,并递归地释放 Node_Value.Reference。

我的问题是我是否正确应用了 Ada 2012,或者如何创建可以是向量/映射或字符串/数字的类型的内存管理递归?

private

    ...

   type Node_Access is access Node;
   type Node_Value is new Ada.Finalization.Controlled with record
      Reference : Node_Access;
   end record;
   overriding procedure Initialize (Item : in out Node_Value);
   overriding procedure Adjust (Item : in out Node_Value);
   overriding procedure Finalize (Item : in out Node_Value);

    ...

   package Of_Array is new Ada.Containers.Indefinite_Vectors (Natural, Node_Value);
   package Of_Object is new Ada.Containers.Indefinite_Ordered_Maps (Wide_String, Node_Value);

   type Node is record
      ...
      Vector    : aliased Of_Array.Vector;
      Object    : aliased Of_Object.Map;
   end record
     with Size => 96;

   procedure Free is new Ada.Unchecked_Deallocation (Node, Node_Access);
4

2 回答 2

1

没有访问类型的自引用类型是类型扩展与不定容器相结合的有效用途。一个简单的例子是 S 表达式或性别。Sex 可以是一个原子,也可以是零个或多个 Sexes 的列表。能够做到这一点的正确方法是

with Ada.Containers.Indefinite_Vectors;
package Sexes is
   type Sex is private;
   -- Operations on Sex
private -- Sexes
   package Sex_List is new Ada.Containers.Indefinite_Vectors
      (Index_Type => Positive, Element_Type => Sex); -- Illegal

   type Sex (Is_Atom : Boolean := False) is record
      case Is_Atom is
      when False =>
         Value : Atom;
      when True =>
         List : Sex_List.Vector;
      end case;
   end record;
end Sexes;

但艾达不允许这样做。我们可以使用类型扩展来解决这个问题:

private -- Sexes
   type Root is tagged null record;

   package Sex_List is new Ada.Containers.Indefinite_Vectors
      (Index_Type => Positive, Element_Type => Root'Class);

   type Sex (Is_Atom : Boolean := False) is new Root with record
      case Is_Atom is
      when False =>
         Value : Atom;
      when True =>
         List : Sex_List.Vector;
      end case;
   end record;
end Sexes;

这是合法的。唯一的问题是您必须将从 List 获取的任何内容转换为 Sex(或您的情况下为 Node)。

HTH; 对迟到的回复感到抱歉。

于 2017-08-23T12:53:56.977 回答
1

这样做的方法(在我看来)是使用 OOP 并有一个抽象元素作为代表可以存储的不同类型数据的类型族的根节点。

然后可以将元素数组实现为以抽象元素类型为根的类的向量。“对象”可以实现为带有字符串键的哈希表,以抽象元素类型为根的类作为值。

于 2017-07-24T17:41:01.100 回答