此功能允许用户创建自定义迭代器。可以写Get (List, Index)
而不是写List (Index)
而不是写for Index in 1 .. List.Max
,而不是写for Index in List'Range
。如果list不是数组,我不确定List'Range
是否可行,也许用户定义的迭代器还有另一种语法。
这是一个Stack或LIFO示例。下一步是隐藏type Stack
成员并为type Stack
List
实现用户定义的迭代器。
with Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Main is
use Ada.Text_IO;
use Ada.Integer_Text_IO;
type Integer_Array is array (Integer range <>) of Integer;
type Stack (Count : Natural) is record
List : Integer_Array (1 .. Count);
Top : Natural := 0;
end record;
procedure Push (Item : Integer; Result : in out Stack) is
begin
Result.Top := Result.Top + 1;
Result.List (Result.Top) := Item;
end;
S : Stack (10);
begin
Push (5, S);
Push (3, S);
Push (8, S);
for I in S.List'First .. S.Top loop
Put (S.List (I), 2);
New_Line;
end loop;
--for I in S'Range loop
--Put (S (I), 2);
--New_Line;
--end loop;
end;
答案 0 :(得分:3)
S'Range
的使用不适用于容器,仅适用于标准数组。这不能改变。
您可能会说for C in S.Iterate loop
调用函数Iterate
并返回循环的每个步骤的游标。此时,您需要使用Element (C)
来访问实际元素(或者更有效Reference (C)
。
第三个版本是for E of S loop
,它直接返回该元素。您无权访问相应的光标。这通常是编写循环的首选方法,除非迭代遍历地图的整个内容,因为无法访问密钥,只能访问该值。
有关如何在自己的数据结构中添加对这些循环的支持的更多信息,您可以查看AdaCore发布的两个宝石:
http://www.adacore.com/adaanswers/gems/gem-127-iterators-in-ada-2012-part-1/
http://www.adacore.com/adaanswers/gems/gem-128-iterators-in-ada-2012-part-2/
我应该提供你需要的所有信息。
答案 1 :(得分:1)
您可以在Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
循环中使用迭代器,如下所示:
for
或者更懒惰的版本:
for C in S.Iterator loop
Put (S (C));
New_Line;
end loop;
实现迭代器是一个相当长的故事,我引用了Ada 2012 rationale(@trashgod也提到过)的详细解释。
答案 2 :(得分:1)
我不确定是否能够迭代堆栈的内容是堆栈正常用例的一部分!除此之外,这是您可以使用广义迭代(ARM 5.5.2)编写的代码:
with Ada.Text_IO;
with Stacks;
procedure Iteration is
use Ada.Text_IO;
S : Stacks.Stack (10);
begin
Stacks.Push (S, 5);
Stacks.Push (S, 3);
Stacks.Push (S, 8);
for C in Stacks.Iterate (S) loop
Put_Line (Stacks.Element (C)'Img); --'
end loop;
end Iteration;
这是Stacks
的可能规范。请注意,System
仅用于私有部分。
with Ada.Iterator_Interfaces;
private with System;
package Stacks is
这些是基本Stack抽象的一部分。请注意,如果您希望能够编写索引访问(My_Stack (42)
或循环for E of My_Stack loop...
),则事情会变得复杂得多。首先,必须标记Stack
。
type Stack (Count : Natural) is private;
procedure Push (To : in out Stack; Item : Integer);
function Element (S : Stack; Index : Positive) return Integer;
公共部分的其余部分是支持广义迭代。
type Cursor is private;
function Has_Element (Pos : Cursor) return Boolean;
function Element (C : Cursor) return Integer;
package Stack_Iterators
is new Ada.Iterator_Interfaces (Cursor, Has_Element);
function Iterate (S : Stack)
return Stack_Iterators.Forward_Iterator’Class; --'
private --'
type Integer_Array is array (Positive range <>) of Integer;
type Stack (Count : Natural) is record
List : Integer_Array (1 .. Count);
Top : Natural := 0;
end record;
function Element (S : Stack; Index : Positive) return Integer
is (S.List (Index));
Cursor
需要引用对象 的游标。我已使用System.Address
来避免使用访问类型并需要Stack
s aliased
。
type Cursor is record
The_Stack : System.Address;
List_Index : Positive := 1;
end record;
end Stacks;
包裹体......
with System.Address_To_Access_Conversions;
package body Stacks is
procedure Push (To : in out Stack; Item : Integer) is
begin
To.Top := To.Top + 1;
To.List (To.Top) := Item;
end Push;
我们必须将Stack
地址转换为指针指向Stack
s。
package Address_Conversions
is new System.Address_To_Access_Conversions (Stack);
function Has_Element (Pos : Cursor) return Boolean is
S : Stack renames Address_Conversions.To_Pointer (Pos.The_Stack).all;
begin
return Pos.List_Index <= S.Top;
end Has_Element;
function Element (C : Cursor) return Integer is
S : Stack renames Address_Conversions.To_Pointer (C.The_Stack).all;
begin
return S.List (C.List_Index);
end Element;
现在为实际的迭代器;我只做过正版。
type Iterator is new Stack_Iterators.Forward_Iterator with record
The_Stack : System.Address;
end record;
overriding function First (Object : Iterator) return Cursor;
overriding function Next (Object : Iterator; Pos : Cursor) return Cursor;
function Iterate (S : Stack)
return Stack_Iterators.Forward_Iterator'Class is --'
begin
-- I seem to be relying on S being passed by reference.
-- This would be OK anyway if Stack was tagged; but it is a
-- reasonable bet that the compiler will pass a large object
-- by reference.
return It : Iterator do
It.The_Stack := S’Address; --'
end return; --'
end Iterate;
function First (Object : Iterator) return Cursor is
begin
return C : Cursor do
C.The_Stack := Object.The_Stack;
C.List_Index := 1;
end return;
end First;
function Next (Object : Iterator; Pos : Cursor) return Cursor is
pragma Unreferenced (Object);
begin
return C : Cursor do
C.The_Stack := Pos.The_Stack;
C.List_Index := Pos.List_Index + 1;
end return;
end Next;
end Stacks;