В Аде, Как мне рекурсивно отобразить и память управлять типом внутри себя
Я боролся с этой маленькой проблемой некоторое время. Я пытаюсь создать свою собственную реализацию внутренней структуры 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);
2 ответа
Способ сделать это (по моему мнению) - использовать ООП и использовать абстрактный элемент в качестве корневого узла семейства типов, представляющих различные виды данных, которые могут быть сохранены.
Затем массив элементов может быть реализован как вектор класса с корнем в типе абстрактного элемента. "Объект" может быть реализован в виде хеш-таблицы со строковым ключом и классом, корнем которого является абстрактный тип элемента, в качестве значений.
Самоссылочные типы без типов доступа являются допустимым использованием для расширения типов в сочетании с неопределенным контейнером. Простой пример - S-выражения или полы. Пол - это либо атом, либо список из нуля или более полов. Правильный способ сделать это будет
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;
что законно Единственный улов заключается в том, что вам нужно преобразовать все, что взято из Списка, в Пол (или в вашем случае в Узел).
НТН; извините за поздний ответ.