如何使用泛型?
How to use a generic type?
我正在处理这里的示例:https://www.adahome.com/rm95/rm9x-12-08.html
我写了我的 generic_stack.ads
:
generic
type Item_Type is private;
size : Positive;
package Generic_Stack is
procedure push( item : in Item_Type );
function pop return Item_Type;
function is_Empty return Boolean;
STACK_EMPTY : exception;
STACK_FULL : exception;
end Generic_Stack;
还有我的 generic_stack.adb
:
package body Generic_Stack
is
type Stack_Table is array (Positive range <>) of Item_Type;
nodes : Stack_Table( 1..size );
index : Natural := 0;
procedure push( item : in Item_Type )
is
begin
if ( index < size )
then
index := index + 1;
nodes(index) := item;
else
raise STACK_FULL;
end if;
end push;
function pop()
return
Item_Type
is
item : Item_Type;
begin
if ( index > 0 )
then
item := nodes( index );
index := index - 1;
else
raise STACK_EMPTY;
end if;
return item;
end pop;
-- function is_Empty() removed for the sake of brevity
end Generic_Stack;
我不太明白如何实际使用 Generic_Stack
。
使用简单的 generic_stack_test.adb
代码:
with Generic_Stack;
package Stack_Int_Type is new Generic_Stack( Item_Type => Integer, Size => 32 );
procedure Generic_Stack_Test
is
stack : Stack_Int_Type;
begin
stack.push( 3 );
end Generic_Stack_Test;
Gnat 给我编译错误:
# gnat make -gnat95 generic_stack_test.adb -o generic_stack_test
x86_64-linux-gnu-gcc-8 -c -gnat95 generic_stack_test.adb
generic_stack_test.adb:9:08: keyword "body" expected here [see file name]
generic_stack_test.adb:20:24: missing "end Stack_Int_Type;"
x86_64-linux-gnu-gnatmake-8: "generic_stack_test.adb" compilation error
我是否必须 declare
Stack_Int_Type
之类的?我不明白如何在过程中使用声明。如果我将 Stack_Int_Type
传递给另一个过程,它是否也必须声明类型?
是否可以在 .ads
中简单地声明 Stack_Int_Type
一次 并将其用作常规类型?我的书和网页有点建议每次都必须声明它,这听起来很繁琐。
您的 Generic_Stack 程序包从未定义堆栈数据类型。
Push 和 Pop 过程是对堆栈的操作。你必须有一个类型来操作。堆栈分为两大类;有界栈和无界栈。您必须决定要创建哪种堆栈。
可以在 https://sworthodoxy.blogspot.com/2019/02/stack-abstract-data-type-using-ada.html
中找到关于在 Ada 中实现的两种堆栈的讨论
在上面 URL 中引用的示例中,您将了解如何创建可多次使用的堆栈类型。来自 Adahome 的示例是一个古老且有问题的示例。你找出了最大的问题。
您的测试代码实际上是两个库项:
with Generic_Stack;
package Stack_Int_Type is new Generic_Stack( Item_Type => Integer, Size => 32 );
声明一个库包Stack_Int_Type
,并且
procedure Generic_Stack_Test
is
stack : Stack_Int_Type;
begin
stack.push( 3 );
end Generic_Stack_Test;
声明一个库过程,就目前而言,它对 Stack_Int_Type
.
一无所知
我们可以通过添加必要的 with
来解决这个问题,但是(使用 -gnatl
编译)
1. with Stack_Int_Type;
2. procedure Generic_Stack_Test
3. is
4. stack : Stack_Int_Type;
|
>>> subtype mark required in this context
>>> found "Stack_Int_Type" declared at stack_int_type.ads:2
5. begin
6. stack.push( 3 );
1 2
>>> invalid prefix in selected component "stack"
>>> prefixed call is only allowed for objects of a tagged type
7. end Generic_Stack_Test;
这里发生的事情是 Generic_Stack
没有声明类型,所以你不能在第 4 行声明它的实例;这是一种单身人士。 (除其他外,这意味着它的命名令人困惑:我称它为 Integer_Stack
。永远不要调用包 _Type
;_Types
,也许吧。)
解决这个问题,
with Generic_Stack;
package Integer_Stack is new Generic_Stack( Item_Type => Integer, Size => 32 );
和
with Integer_Stack;
procedure Generic_Stack_Test
is
begin
Integer_Stack.push( 3 );
end Generic_Stack_Test;
您可以将 Integer_Stack
设为本地:
with Generic_Stack;
procedure Generic_Stack_Test
is
package Integer_Stack
is new Generic_Stack( Item_Type => Integer, Size => 32 );
begin
Integer_Stack.push( 3 );
end Generic_Stack_Test;
如别处所述,您的程序包规范未定义任何类型。否则,您会在 package
关键字之后的某处有 type ... is
。就这么简单。
但正如其他地方所解释的那样,这并不戏剧化。您的包实例化将准确定义 one 堆栈,而不是要在多个地方使用的类型。在某些情况下,这正是您所需要的。因此,您可以调用您的实例化包 My_Stack
,它实际上围绕一个对象(My_Stack.nodes
,只能通过 Push
和 Pop
访问)。
您需要在一个单元(过程、程序包...)中对 Generic_Stack
进行实例化。在它之外,它是 "outer space" 只有 with
和 use
子句需要与其他单元连接。
with Generic_Stack;
procedure Generic_Stack_Test
is
package My_Stack is new Generic_Stack( Item_Type => Integer, Size => 32 );
begin
My_Stack.push( 3 );
end Generic_Stack_Test;
我正在处理这里的示例:https://www.adahome.com/rm95/rm9x-12-08.html
我写了我的 generic_stack.ads
:
generic
type Item_Type is private;
size : Positive;
package Generic_Stack is
procedure push( item : in Item_Type );
function pop return Item_Type;
function is_Empty return Boolean;
STACK_EMPTY : exception;
STACK_FULL : exception;
end Generic_Stack;
还有我的 generic_stack.adb
:
package body Generic_Stack
is
type Stack_Table is array (Positive range <>) of Item_Type;
nodes : Stack_Table( 1..size );
index : Natural := 0;
procedure push( item : in Item_Type )
is
begin
if ( index < size )
then
index := index + 1;
nodes(index) := item;
else
raise STACK_FULL;
end if;
end push;
function pop()
return
Item_Type
is
item : Item_Type;
begin
if ( index > 0 )
then
item := nodes( index );
index := index - 1;
else
raise STACK_EMPTY;
end if;
return item;
end pop;
-- function is_Empty() removed for the sake of brevity
end Generic_Stack;
我不太明白如何实际使用 Generic_Stack
。
使用简单的 generic_stack_test.adb
代码:
with Generic_Stack;
package Stack_Int_Type is new Generic_Stack( Item_Type => Integer, Size => 32 );
procedure Generic_Stack_Test
is
stack : Stack_Int_Type;
begin
stack.push( 3 );
end Generic_Stack_Test;
Gnat 给我编译错误:
# gnat make -gnat95 generic_stack_test.adb -o generic_stack_test
x86_64-linux-gnu-gcc-8 -c -gnat95 generic_stack_test.adb
generic_stack_test.adb:9:08: keyword "body" expected here [see file name]
generic_stack_test.adb:20:24: missing "end Stack_Int_Type;"
x86_64-linux-gnu-gnatmake-8: "generic_stack_test.adb" compilation error
我是否必须 declare
Stack_Int_Type
之类的?我不明白如何在过程中使用声明。如果我将 Stack_Int_Type
传递给另一个过程,它是否也必须声明类型?
是否可以在 .ads
中简单地声明 Stack_Int_Type
一次 并将其用作常规类型?我的书和网页有点建议每次都必须声明它,这听起来很繁琐。
您的 Generic_Stack 程序包从未定义堆栈数据类型。 Push 和 Pop 过程是对堆栈的操作。你必须有一个类型来操作。堆栈分为两大类;有界栈和无界栈。您必须决定要创建哪种堆栈。 可以在 https://sworthodoxy.blogspot.com/2019/02/stack-abstract-data-type-using-ada.html
中找到关于在 Ada 中实现的两种堆栈的讨论在上面 URL 中引用的示例中,您将了解如何创建可多次使用的堆栈类型。来自 Adahome 的示例是一个古老且有问题的示例。你找出了最大的问题。
您的测试代码实际上是两个库项:
with Generic_Stack;
package Stack_Int_Type is new Generic_Stack( Item_Type => Integer, Size => 32 );
声明一个库包Stack_Int_Type
,并且
procedure Generic_Stack_Test
is
stack : Stack_Int_Type;
begin
stack.push( 3 );
end Generic_Stack_Test;
声明一个库过程,就目前而言,它对 Stack_Int_Type
.
一无所知
我们可以通过添加必要的 with
来解决这个问题,但是(使用 -gnatl
编译)
1. with Stack_Int_Type;
2. procedure Generic_Stack_Test
3. is
4. stack : Stack_Int_Type;
|
>>> subtype mark required in this context
>>> found "Stack_Int_Type" declared at stack_int_type.ads:2
5. begin
6. stack.push( 3 );
1 2
>>> invalid prefix in selected component "stack"
>>> prefixed call is only allowed for objects of a tagged type
7. end Generic_Stack_Test;
这里发生的事情是 Generic_Stack
没有声明类型,所以你不能在第 4 行声明它的实例;这是一种单身人士。 (除其他外,这意味着它的命名令人困惑:我称它为 Integer_Stack
。永远不要调用包 _Type
;_Types
,也许吧。)
解决这个问题,
with Generic_Stack;
package Integer_Stack is new Generic_Stack( Item_Type => Integer, Size => 32 );
和
with Integer_Stack;
procedure Generic_Stack_Test
is
begin
Integer_Stack.push( 3 );
end Generic_Stack_Test;
您可以将 Integer_Stack
设为本地:
with Generic_Stack;
procedure Generic_Stack_Test
is
package Integer_Stack
is new Generic_Stack( Item_Type => Integer, Size => 32 );
begin
Integer_Stack.push( 3 );
end Generic_Stack_Test;
如别处所述,您的程序包规范未定义任何类型。否则,您会在 package
关键字之后的某处有 type ... is
。就这么简单。
但正如其他地方所解释的那样,这并不戏剧化。您的包实例化将准确定义 one 堆栈,而不是要在多个地方使用的类型。在某些情况下,这正是您所需要的。因此,您可以调用您的实例化包 My_Stack
,它实际上围绕一个对象(My_Stack.nodes
,只能通过 Push
和 Pop
访问)。
您需要在一个单元(过程、程序包...)中对 Generic_Stack
进行实例化。在它之外,它是 "outer space" 只有 with
和 use
子句需要与其他单元连接。
with Generic_Stack;
procedure Generic_Stack_Test
is
package My_Stack is new Generic_Stack( Item_Type => Integer, Size => 32 );
begin
My_Stack.push( 3 );
end Generic_Stack_Test;