Ada:具有可变大小数组属性的对象
Ada: objects with variable-sized array attribute
我想在描述二维离散 space 的包内创建一个标记类型,其大小在 运行 时间内确定。
(上下文:实施 game of life)
我发现的第一个方法是通用性:
generic
Size : Natural;
package Worlds is
type World_Type is tagged private;
type World is access World_Type'Class;
subtype Coordinate is Positive range 1..Size;
private
type World_Array is array (Coordinate, Coordinate) of Boolean;
type World_Type is tagged record
Content : World_Array;
end record;
end Worlds;
但是,在为世界实现访问者时,通用性成为一个大问题:
with Worlds;
package World_Visitors is
type World_Visitor_Type is tagged private;
type World_Visitor is access World_Visitor_Type'Class;
procedure Visite(v : World_Visitor_Type;
w : in out Worlds.World); -- ERROR: invalid prefix in selected component "Worlds"
private
type World_Visitor_Type is tagged null record;
end World_Visitors;
GNAT 无法编译它,因为 Worlds 是一个通用包。
然后,因为我不想为每个可能的世界大小编写一个访问者,所以我尝试了 C++ 方式:将大小声明为标记类型中的属性。
package Worlds is
type World_Type is tagged private;
type World is access World_Type'Class;
subtype Coordinate is Positive range <>;
function Init(Size : Natural) return World; -- initialize Content attribute as an array of length (Size*Size)
private
type World_Array is array (Coordinate, Coordinate) of Boolean;
type World_Type is tagged record
Content : World_Array;
Size : Natural;
end record;
end Worlds;
并且,预计这不起作用,因为 World_Array 需要明确的坐标范围。
事实上,我不知道如何在标记类型中创建 运行-time-chosen 大小的数组。
我从 here, here, here or here 那里得到了一些想法,但在这种情况下似乎没有任何意义。
Ada如何实现可变大小数组属性的对象?
procedure Visite(v : World_Visitor_Type;
w : in out Worlds.World); -- ERROR: invalid prefix in selected component "Worlds"
这永远行不通——这是因为 Worlds 是一个通用包,类型方面没有 Worlds.World 这样的实际事物。 (这就是说参数类型 w
永远无法匹配实例化。)
解决此问题的一种方法是使 World_Visitors
具有通用性,并将 Worlds 作为参数。像这样:
generic
X : Positive;
package temp is
subtype Index is Integer range 1..X;
end temp;
generic
with package K is new temp(<>);
package temp_dependant is
-- Note that parameter I now CAN depend on temp, via formal parameter K.
function J( I: K.Index ) return Boolean is (True);
end temp_dependant;
另一种方法是将访问者移动到世界包中。
另一种方法是使访问者的包裹成为 Worlds 的子包裹。
解决此问题的常规 Ada 方法是使用 判别式(参见 ARM 3.7)。
在你的情况下,这看起来像
package Worlds is
type World_Type (Size : Natural) is tagged private;
type World is access World_Type’Class; -- ‘’ to fix SO colour bug
private
type World_Array is array (Positive range <>, Positive range <>) of Boolean;
type World_Type (Size : Natural) is tagged record
Content : World_Array (1 .. Size, 1 .. Size);
end record;
end Worlds;
其中 World_Array
是 无约束数组类型 (ARM 3.6) 的示例。您将通过
这样的代码创建一个新世界
W : Worlds.World := new Worlds.World_Type (Size => 100);
请注意,您无法在创建对象后更改 Size
。
我遗漏了Coordinate
;如果没有 Init
,您可能会逃脱,特别是如果您为 Content
:
提供初始化程序
Content : World_Array (1 .. Size, 1 .. Size) :=
(others => (others => False));
已编辑 26.iii.15:代码正在创建大小为 Size + 1
x Size + 1
.
的数组
我想在描述二维离散 space 的包内创建一个标记类型,其大小在 运行 时间内确定。 (上下文:实施 game of life)
我发现的第一个方法是通用性:
generic
Size : Natural;
package Worlds is
type World_Type is tagged private;
type World is access World_Type'Class;
subtype Coordinate is Positive range 1..Size;
private
type World_Array is array (Coordinate, Coordinate) of Boolean;
type World_Type is tagged record
Content : World_Array;
end record;
end Worlds;
但是,在为世界实现访问者时,通用性成为一个大问题:
with Worlds;
package World_Visitors is
type World_Visitor_Type is tagged private;
type World_Visitor is access World_Visitor_Type'Class;
procedure Visite(v : World_Visitor_Type;
w : in out Worlds.World); -- ERROR: invalid prefix in selected component "Worlds"
private
type World_Visitor_Type is tagged null record;
end World_Visitors;
GNAT 无法编译它,因为 Worlds 是一个通用包。 然后,因为我不想为每个可能的世界大小编写一个访问者,所以我尝试了 C++ 方式:将大小声明为标记类型中的属性。
package Worlds is
type World_Type is tagged private;
type World is access World_Type'Class;
subtype Coordinate is Positive range <>;
function Init(Size : Natural) return World; -- initialize Content attribute as an array of length (Size*Size)
private
type World_Array is array (Coordinate, Coordinate) of Boolean;
type World_Type is tagged record
Content : World_Array;
Size : Natural;
end record;
end Worlds;
并且,预计这不起作用,因为 World_Array 需要明确的坐标范围。 事实上,我不知道如何在标记类型中创建 运行-time-chosen 大小的数组。 我从 here, here, here or here 那里得到了一些想法,但在这种情况下似乎没有任何意义。
Ada如何实现可变大小数组属性的对象?
procedure Visite(v : World_Visitor_Type;
w : in out Worlds.World); -- ERROR: invalid prefix in selected component "Worlds"
这永远行不通——这是因为 Worlds 是一个通用包,类型方面没有 Worlds.World 这样的实际事物。 (这就是说参数类型 w
永远无法匹配实例化。)
解决此问题的一种方法是使 World_Visitors
具有通用性,并将 Worlds 作为参数。像这样:
generic
X : Positive;
package temp is
subtype Index is Integer range 1..X;
end temp;
generic
with package K is new temp(<>);
package temp_dependant is
-- Note that parameter I now CAN depend on temp, via formal parameter K.
function J( I: K.Index ) return Boolean is (True);
end temp_dependant;
另一种方法是将访问者移动到世界包中。 另一种方法是使访问者的包裹成为 Worlds 的子包裹。
解决此问题的常规 Ada 方法是使用 判别式(参见 ARM 3.7)。
在你的情况下,这看起来像
package Worlds is
type World_Type (Size : Natural) is tagged private;
type World is access World_Type’Class; -- ‘’ to fix SO colour bug
private
type World_Array is array (Positive range <>, Positive range <>) of Boolean;
type World_Type (Size : Natural) is tagged record
Content : World_Array (1 .. Size, 1 .. Size);
end record;
end Worlds;
其中 World_Array
是 无约束数组类型 (ARM 3.6) 的示例。您将通过
W : Worlds.World := new Worlds.World_Type (Size => 100);
请注意,您无法在创建对象后更改 Size
。
我遗漏了Coordinate
;如果没有 Init
,您可能会逃脱,特别是如果您为 Content
:
Content : World_Array (1 .. Size, 1 .. Size) :=
(others => (others => False));
已编辑 26.iii.15:代码正在创建大小为 Size + 1
x Size + 1
.