Ada 匹配数组
Ada Matchup Array
我在 ada 中有一个函数,它必须将大量布尔值检查为 return 一个(稀疏)值。这很难用语言解释,所以这里有一个'ideal'在ada中不起作用的解决方案(注意我有超过3种挑战者类型和更严格的逻辑):
type ChallengerType is (Rock,Paper,Scissors,Suicide,None);
type Challengers is array (ChallengerType) of Boolean;
pragma Pack(Challengers);
-- NOT legal, challengers is not an enumeration type
matchups : array (Challengers) of ChallengerType := (
-- Single challenger victories
(Rock => True, others => False) => Rock,
(Paper => True, others => False) => Paper,
(Scissors => True, others => False) => Scissors,
-- Double challenger victories
(Rock => True, Paper => True, others => False) => Paper,
(Rock => True, Scissors => True, others => False) => Rock,
(Paper => True, Scissors => True, others => False) => Scissors,
-- All the rest either are ambiguous (RPS) or suicided
others => None)
这在 Ada 中是不合法的,所以我选择了更 c 风格的版本,其中我的数组是 Integer range 0..2#11111#
并编写了一个转换器。然而,代码变得不那么干净了(例如:(2#00101# => Scissors)
不那么清晰)。
'best' 实现这样一个对战数组的方法是什么?
总结:我想要一个从枚举类型的幂集到它的值之一的映射。 IE:如果我的枚举是 {A,B,C} 我想从 {{},{A},{B},{C},{A,B},{A,C},{B, C},{A,B,C}}到{A,B,C}。我也事先知道映射中的大多数值都是同一类型,因此 others
关键字非常好用。目前我使用带有“1”的二进制索引,这意味着指定的枚举元素存在,但我希望我能更明确。
不是答案...发帖以防有人看到前进的方向。
这扩展了我上面的评论:就从数组生成离散类型而言,它似乎有效...
with Ada.Unchecked_Conversion;
package RPS is
type ChallengerType is (Rock,Paper,Scissors,Suicide,None);
for ChallengerType use (Rock => 1, Paper => 2,Scissors => 4,Suicide => 8,None => 16);
type Challengers is array (ChallengerType) of Boolean with Pack;
type Challengers_int is range 0 .. 31;
function IDX is new Ada.Unchecked_Conversion(Challengers, Challengers_int);
Rock_Only : constant Challengers := (Rock => True, others => False);
Rock_IDX : constant Challengers_int := IDX(Rock_Only);
matchups : constant array (Challengers_int) of ChallengerType := (
-- Single challenger victories
-- Rock_IDX => Rock, -- fails
1 => Rock,
IDX((Paper => True, others => False)) => Paper, -- fails
IDX((Scissors => True, others => False)) => Scissors,
-- Double challenger victories
IDX((Rock => True, Paper => True, others => False)) => Paper,
IDX((Rock => True, Scissors => True, others => False)) => Rock,
IDX((Paper => True, Scissors => True, others => False)) => Scissors,
-- All the rest either are ambiguous (RPS) or suicided
others => None);
end RPS;
但是,编译失败,dynamic or empty choice in aggregate must be the only choice
在数组中的任一注释行 - 即使索引是常量而不是表达式。
Case 语句同样失败:
case IDX(C) is
when Rock_IDX => return Rock;
when IDX((Paper => True, others => False)) => return Paper;
...
编译器报告:
rps.adb:11:10: choice given in case statement is not static
rps.adb:11:10: "Rock_IDX" is not a static constant (RM 4.9(5))
rps.adb:12:10: choice given in case statement is not static
rps.adb:12:10: non-static function call (RM 4.9(6,18)) rps.adb:12:14:
static expression must have scalar or string type (RM 4.9(2))
这是一种解决方案:
with Ada.Text_IO; use Ada.text_IO;
procedure Mapping_Question is
type ChallengerType is (Rock,Paper,Scissors,Suicide,None);
type Challengers is array (ChallengerType range <>) of Boolean with Pack;
Type Mapped_Challenges is array(Positive range <>) of ChallengerType;
function Map_Challengers(Item : Challengers) return Mapped_Challenges is
function Mapper(Item : Challengers) return Mapped_Challenges is
Single : Mapped_Challenges(1..1);
begin
for I in Item'Range loop
if Item(I) then
if I < Item'Last then
return I & Mapper(Item(ChallengerType'Succ(I)..Item'Last));
else
Single(Single'First) := I;
return Single;
end if;
end if;
end loop;
Single(Single'First) := None;
return Single;
end Mapper;
begin
return Mapper(Item);
end Map_Challengers;
procedure Print_Challenges(Item : Mapped_Challenges) is
begin
for I in Item'Range loop
Put_Line(ChallengerType'Image(Item(I)));
end loop;
end Print_Challenges;
Foo : Challengers(Rock..None) := (Rock..Scissors => True, Others => False);
begin
declare
Mapping : Mapped_Challenges := Map_Challengers(Foo);
begin
if Mapping'Length > 1 then
Print_Challenges(Mapping(Mapping'First..Mapping'Last - 1));
else
Print_challenges(Mapping);
end if;
end;
end Mapping_Question;
一个更简单的答案使用 Ada.Containers.Vectors 包中的 Vector 类型:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
use Type Ada.Containers.Count_Type;
procedure Mapping_Vector is
type ChallengerType is (Rock,Paper,Scissors,Suicide,None);
type Challengers is array (ChallengerType) of Boolean with Pack;
package Challenge_Vect is new Ada.Containers.Vectors(Positive, ChallengerType);
use Challenge_Vect;
function Map_Challengers(Item : in Challengers) return Vector is
Result : Vector := Empty_Vector;
begin
for I in Item'Range loop
if Item(I) then
Result.Append(I);
end if;
end loop;
return Result;
end Map_Challengers;
Foo : Challengers := (Rock..Scissors => True, Others => False);
Mapped_Challengers : Vector := Map_Challengers(Foo);
begin
If Mapped_Challengers.Length > 0 then
for C of Mapped_Challengers loop
Put_Line(ChallengerType'Image(C));
end loop;
else
Put_Line("No challengers were TRUE");
end if;
end Mapping_Vector;
这不是一个纯静态的解决方案,但它可以根据枚举值优雅地配置映射,即使现实中的映射数组是由模块化类型索引的:
规格:
with Ada.Text_IO;
with Ada.Unchecked_Conversion;
generic
type Element_Type is (<>);
type Numeric_Type is mod <>;
package Set_With_Modular_Representation is
type Instance is array (Element_Type) of Boolean with Pack;
Empty_Set : constant Numeric_Type := 0;
E : Numeric_Type renames Empty_Set; -- Got a request not to use Ø.
function "&" (Left : in Instance;
Right : in Instance) return Numeric_Type;
function "&" (Left : in Numeric_Type;
Right : in Instance) return Numeric_Type;
function "&" (Left : in Element_Type;
Right : in Element_Type) return Numeric_Type;
function "&" (Left : in Numeric_Type;
Right : in Element_Type) return Numeric_Type;
private
pragma Assert (Numeric_Type'Modulus = 2 ** Instance'Size);
pragma Assert (Numeric_Type'Size = Instance'Size);
function Numeric is
new Ada.Unchecked_Conversion (Source => Instance,
Target => Numeric_Type);
function Numeric (Item : in Element_Type) return Numeric_Type;
end Set_With_Modular_Representation;
实施:
package body Set_With_Modular_Representation is
function "&" (Left : in Instance;
Right : in Instance) return Numeric_Type is
begin
return Numeric (Left) or Numeric (Right);
end "&";
function "&" (Left : in Numeric_Type;
Right : in Instance) return Numeric_Type is
begin
return Left or Numeric (Right);
end "&";
function "&" (Left : in Element_Type;
Right : in Element_Type) return Numeric_Type is
begin
return Numeric (Left) or Numeric (Right);
end "&";
function "&" (Left : in Numeric_Type;
Right : in Element_Type) return Numeric_Type is
begin
return Left or Numeric (Right);
end "&";
function Numeric (Item : in Element_Type) return Numeric_Type is
Buffer : Instance := (others => False);
begin
Buffer (Item) := True;
return Numeric (Buffer);
end Numeric;
end Set_With_Modular_Representation;
示范:
with Ada.Command_Line;
with Ada.Text_IO;
with Set_With_Modular_Representation;
procedure Set_With_Modular_Representation_Demo is
type Outcomes is (Paper, Rock, Scissors, Suicide, None);
subtype Choices is Outcomes range Paper .. Scissors;
type Numeric_Choices is mod 2 ** 3;
package Choice_Set is
new Set_With_Modular_Representation (Element_Type => Choices,
Numeric_Type => Numeric_Choices);
use Choice_Set;
Mapping : array (Numeric_Choices) of Outcomes := (others => None);
begin
Set_Up_Mapping :
begin
-- Single challenger victories
Mapping (E & Rock) := Rock;
Mapping (E & Paper) := Paper;
Mapping (E & Scissors) := Scissors;
-- Double challenger victories
Mapping (Rock & Paper) := Paper;
Mapping (Rock & Scissors) := Rock;
Mapping (Paper & Scissors) := Scissors;
end Set_Up_Mapping;
Test :
declare
package Outcome_Text_IO is
new Ada.Text_IO.Enumeration_IO (Outcomes);
use Ada.Command_Line, Ada.Text_IO, Outcome_Text_IO;
Chosen : Numeric_Choices := E;
begin
for Index in 1 .. Argument_Count loop
Chosen := Chosen & Choices'Value (Argument (Index)); -- '
end loop;
Put ("Outcome: ");
Put (Mapping (Chosen));
New_Line;
end Test;
end Set_With_Modular_Representation_Demo;
以下方法使用了各种柯里化。为了进一步简化示例,我将枚举类型缩短为三个值。解决方案是静态的,但是直接使用枚举值的“优雅”已经消失了。如果不需要静态常量,那么,正如其他方法所示,常量函数表 F
和 T
从 ChallengerType
到 Boolean
将是可能的,然后命名组件显示为 T (Paper) => ...
等
pragma Pure (Rps);
type ChallengerType is (Rock,Paper,None);
type Challengers1 is array (Boolean) of Challengertype;
type Challengers2 is array (Boolean) of Challengers1;
type Challengers3 is array (Boolean) of Challengers2;
Matchups : constant Challengers3 :=
-- Rock:
(True => --> Paper:
(True => --> None:
(False => Paper,
True => None),
False => --> None:
(others => Rock)),
-- Rock:
False => --> Paper:
(True => --> None:
(False => Paper,
True => None),
False =>
(others => None))
);
使用常量的解决方案
这不是一个优雅的解决方案,但作为更好的解决方案的一部分可能会有所帮助。
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with System;
with System.Unsigned_Types;
procedure Main is
subtype S is System.Unsigned_Types.Unsigned range 0 .. 31;
use type S;
function Shift_Left (Value : S; Amount : Natural) return S renames System.Unsigned_Types.Shift_Left;
Rock : constant S := Shift_Left (1, 0);
Paper : constant S := Shift_Left (1, 1);
Scissors : constant S := Shift_Left (1, 2);
Suicide : constant S := Shift_Left (1, 3);
None : constant S := Shift_Left (1, 4);
P : array (S) of S := (others => None);
begin
P (Rock or Paper) := Paper;
P (Rock or Scissors) := Rock;
P (Paper or Scissors) := Scissors;
Put_Line ("P(Paper or Scissors) = Scissors");
Put ("P(");
Put (Integer (Paper), 0, 2);
Put (" or ");
Put (Integer (Scissors), 0, 2);
Put (") = P(");
Put (Integer (Paper or Scissors), 0, 2);
Put (") = ");
Put (Integer (P (Paper or Scissors)), 0, 2);
Put ("");
end;
结果
P(Paper or Scissors) = Scissors
P(2#10# or 2#100#) = P(2#110#) = 2#100#
使用枚举的解决方案
with Ada.Text_IO; use Ada.Text_IO;
with System;
with System.Unsigned_Types;
procedure Main is
type T is (Rock, Paper, Scissors, Suicide, None);
subtype S is System.Unsigned_Types.Unsigned range 0 .. 31;
use type S;
function B (Value : T) return S is (System.Unsigned_Types.Shift_Left (1, T'Pos (Value)));
function "&" (Left : T; Right : T) return S is (System.Unsigned_Types."or" (B (Left), B (Right)));
P : array (S) of T := (others => None);
begin
P (Rock & Paper) := Paper;
P (Rock & Scissors) := Rock;
P (Paper & Scissors) := Scissors;
Put_Line (T'Image (P (Rock & Paper)));
Put_Line (T'Image (P (Rock & Scissors)));
Put_Line (T'Image (P (Paper & Scissors)));
end;
结果
PAPER
ROCK
SCISSORS
我在 ada 中有一个函数,它必须将大量布尔值检查为 return 一个(稀疏)值。这很难用语言解释,所以这里有一个'ideal'在ada中不起作用的解决方案(注意我有超过3种挑战者类型和更严格的逻辑):
type ChallengerType is (Rock,Paper,Scissors,Suicide,None);
type Challengers is array (ChallengerType) of Boolean;
pragma Pack(Challengers);
-- NOT legal, challengers is not an enumeration type
matchups : array (Challengers) of ChallengerType := (
-- Single challenger victories
(Rock => True, others => False) => Rock,
(Paper => True, others => False) => Paper,
(Scissors => True, others => False) => Scissors,
-- Double challenger victories
(Rock => True, Paper => True, others => False) => Paper,
(Rock => True, Scissors => True, others => False) => Rock,
(Paper => True, Scissors => True, others => False) => Scissors,
-- All the rest either are ambiguous (RPS) or suicided
others => None)
这在 Ada 中是不合法的,所以我选择了更 c 风格的版本,其中我的数组是 Integer range 0..2#11111#
并编写了一个转换器。然而,代码变得不那么干净了(例如:(2#00101# => Scissors)
不那么清晰)。
'best' 实现这样一个对战数组的方法是什么?
总结:我想要一个从枚举类型的幂集到它的值之一的映射。 IE:如果我的枚举是 {A,B,C} 我想从 {{},{A},{B},{C},{A,B},{A,C},{B, C},{A,B,C}}到{A,B,C}。我也事先知道映射中的大多数值都是同一类型,因此 others
关键字非常好用。目前我使用带有“1”的二进制索引,这意味着指定的枚举元素存在,但我希望我能更明确。
不是答案...发帖以防有人看到前进的方向。
这扩展了我上面的评论:就从数组生成离散类型而言,它似乎有效...
with Ada.Unchecked_Conversion;
package RPS is
type ChallengerType is (Rock,Paper,Scissors,Suicide,None);
for ChallengerType use (Rock => 1, Paper => 2,Scissors => 4,Suicide => 8,None => 16);
type Challengers is array (ChallengerType) of Boolean with Pack;
type Challengers_int is range 0 .. 31;
function IDX is new Ada.Unchecked_Conversion(Challengers, Challengers_int);
Rock_Only : constant Challengers := (Rock => True, others => False);
Rock_IDX : constant Challengers_int := IDX(Rock_Only);
matchups : constant array (Challengers_int) of ChallengerType := (
-- Single challenger victories
-- Rock_IDX => Rock, -- fails
1 => Rock,
IDX((Paper => True, others => False)) => Paper, -- fails
IDX((Scissors => True, others => False)) => Scissors,
-- Double challenger victories
IDX((Rock => True, Paper => True, others => False)) => Paper,
IDX((Rock => True, Scissors => True, others => False)) => Rock,
IDX((Paper => True, Scissors => True, others => False)) => Scissors,
-- All the rest either are ambiguous (RPS) or suicided
others => None);
end RPS;
但是,编译失败,dynamic or empty choice in aggregate must be the only choice
在数组中的任一注释行 - 即使索引是常量而不是表达式。
Case 语句同样失败:
case IDX(C) is
when Rock_IDX => return Rock;
when IDX((Paper => True, others => False)) => return Paper;
...
编译器报告:
rps.adb:11:10: choice given in case statement is not static
rps.adb:11:10: "Rock_IDX" is not a static constant (RM 4.9(5))
rps.adb:12:10: choice given in case statement is not static
rps.adb:12:10: non-static function call (RM 4.9(6,18)) rps.adb:12:14:
static expression must have scalar or string type (RM 4.9(2))
这是一种解决方案:
with Ada.Text_IO; use Ada.text_IO;
procedure Mapping_Question is
type ChallengerType is (Rock,Paper,Scissors,Suicide,None);
type Challengers is array (ChallengerType range <>) of Boolean with Pack;
Type Mapped_Challenges is array(Positive range <>) of ChallengerType;
function Map_Challengers(Item : Challengers) return Mapped_Challenges is
function Mapper(Item : Challengers) return Mapped_Challenges is
Single : Mapped_Challenges(1..1);
begin
for I in Item'Range loop
if Item(I) then
if I < Item'Last then
return I & Mapper(Item(ChallengerType'Succ(I)..Item'Last));
else
Single(Single'First) := I;
return Single;
end if;
end if;
end loop;
Single(Single'First) := None;
return Single;
end Mapper;
begin
return Mapper(Item);
end Map_Challengers;
procedure Print_Challenges(Item : Mapped_Challenges) is
begin
for I in Item'Range loop
Put_Line(ChallengerType'Image(Item(I)));
end loop;
end Print_Challenges;
Foo : Challengers(Rock..None) := (Rock..Scissors => True, Others => False);
begin
declare
Mapping : Mapped_Challenges := Map_Challengers(Foo);
begin
if Mapping'Length > 1 then
Print_Challenges(Mapping(Mapping'First..Mapping'Last - 1));
else
Print_challenges(Mapping);
end if;
end;
end Mapping_Question;
一个更简单的答案使用 Ada.Containers.Vectors 包中的 Vector 类型:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
use Type Ada.Containers.Count_Type;
procedure Mapping_Vector is
type ChallengerType is (Rock,Paper,Scissors,Suicide,None);
type Challengers is array (ChallengerType) of Boolean with Pack;
package Challenge_Vect is new Ada.Containers.Vectors(Positive, ChallengerType);
use Challenge_Vect;
function Map_Challengers(Item : in Challengers) return Vector is
Result : Vector := Empty_Vector;
begin
for I in Item'Range loop
if Item(I) then
Result.Append(I);
end if;
end loop;
return Result;
end Map_Challengers;
Foo : Challengers := (Rock..Scissors => True, Others => False);
Mapped_Challengers : Vector := Map_Challengers(Foo);
begin
If Mapped_Challengers.Length > 0 then
for C of Mapped_Challengers loop
Put_Line(ChallengerType'Image(C));
end loop;
else
Put_Line("No challengers were TRUE");
end if;
end Mapping_Vector;
这不是一个纯静态的解决方案,但它可以根据枚举值优雅地配置映射,即使现实中的映射数组是由模块化类型索引的:
规格:
with Ada.Text_IO;
with Ada.Unchecked_Conversion;
generic
type Element_Type is (<>);
type Numeric_Type is mod <>;
package Set_With_Modular_Representation is
type Instance is array (Element_Type) of Boolean with Pack;
Empty_Set : constant Numeric_Type := 0;
E : Numeric_Type renames Empty_Set; -- Got a request not to use Ø.
function "&" (Left : in Instance;
Right : in Instance) return Numeric_Type;
function "&" (Left : in Numeric_Type;
Right : in Instance) return Numeric_Type;
function "&" (Left : in Element_Type;
Right : in Element_Type) return Numeric_Type;
function "&" (Left : in Numeric_Type;
Right : in Element_Type) return Numeric_Type;
private
pragma Assert (Numeric_Type'Modulus = 2 ** Instance'Size);
pragma Assert (Numeric_Type'Size = Instance'Size);
function Numeric is
new Ada.Unchecked_Conversion (Source => Instance,
Target => Numeric_Type);
function Numeric (Item : in Element_Type) return Numeric_Type;
end Set_With_Modular_Representation;
实施:
package body Set_With_Modular_Representation is
function "&" (Left : in Instance;
Right : in Instance) return Numeric_Type is
begin
return Numeric (Left) or Numeric (Right);
end "&";
function "&" (Left : in Numeric_Type;
Right : in Instance) return Numeric_Type is
begin
return Left or Numeric (Right);
end "&";
function "&" (Left : in Element_Type;
Right : in Element_Type) return Numeric_Type is
begin
return Numeric (Left) or Numeric (Right);
end "&";
function "&" (Left : in Numeric_Type;
Right : in Element_Type) return Numeric_Type is
begin
return Left or Numeric (Right);
end "&";
function Numeric (Item : in Element_Type) return Numeric_Type is
Buffer : Instance := (others => False);
begin
Buffer (Item) := True;
return Numeric (Buffer);
end Numeric;
end Set_With_Modular_Representation;
示范:
with Ada.Command_Line;
with Ada.Text_IO;
with Set_With_Modular_Representation;
procedure Set_With_Modular_Representation_Demo is
type Outcomes is (Paper, Rock, Scissors, Suicide, None);
subtype Choices is Outcomes range Paper .. Scissors;
type Numeric_Choices is mod 2 ** 3;
package Choice_Set is
new Set_With_Modular_Representation (Element_Type => Choices,
Numeric_Type => Numeric_Choices);
use Choice_Set;
Mapping : array (Numeric_Choices) of Outcomes := (others => None);
begin
Set_Up_Mapping :
begin
-- Single challenger victories
Mapping (E & Rock) := Rock;
Mapping (E & Paper) := Paper;
Mapping (E & Scissors) := Scissors;
-- Double challenger victories
Mapping (Rock & Paper) := Paper;
Mapping (Rock & Scissors) := Rock;
Mapping (Paper & Scissors) := Scissors;
end Set_Up_Mapping;
Test :
declare
package Outcome_Text_IO is
new Ada.Text_IO.Enumeration_IO (Outcomes);
use Ada.Command_Line, Ada.Text_IO, Outcome_Text_IO;
Chosen : Numeric_Choices := E;
begin
for Index in 1 .. Argument_Count loop
Chosen := Chosen & Choices'Value (Argument (Index)); -- '
end loop;
Put ("Outcome: ");
Put (Mapping (Chosen));
New_Line;
end Test;
end Set_With_Modular_Representation_Demo;
以下方法使用了各种柯里化。为了进一步简化示例,我将枚举类型缩短为三个值。解决方案是静态的,但是直接使用枚举值的“优雅”已经消失了。如果不需要静态常量,那么,正如其他方法所示,常量函数表 F
和 T
从 ChallengerType
到 Boolean
将是可能的,然后命名组件显示为 T (Paper) => ...
等
pragma Pure (Rps);
type ChallengerType is (Rock,Paper,None);
type Challengers1 is array (Boolean) of Challengertype;
type Challengers2 is array (Boolean) of Challengers1;
type Challengers3 is array (Boolean) of Challengers2;
Matchups : constant Challengers3 :=
-- Rock:
(True => --> Paper:
(True => --> None:
(False => Paper,
True => None),
False => --> None:
(others => Rock)),
-- Rock:
False => --> Paper:
(True => --> None:
(False => Paper,
True => None),
False =>
(others => None))
);
使用常量的解决方案
这不是一个优雅的解决方案,但作为更好的解决方案的一部分可能会有所帮助。
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with System;
with System.Unsigned_Types;
procedure Main is
subtype S is System.Unsigned_Types.Unsigned range 0 .. 31;
use type S;
function Shift_Left (Value : S; Amount : Natural) return S renames System.Unsigned_Types.Shift_Left;
Rock : constant S := Shift_Left (1, 0);
Paper : constant S := Shift_Left (1, 1);
Scissors : constant S := Shift_Left (1, 2);
Suicide : constant S := Shift_Left (1, 3);
None : constant S := Shift_Left (1, 4);
P : array (S) of S := (others => None);
begin
P (Rock or Paper) := Paper;
P (Rock or Scissors) := Rock;
P (Paper or Scissors) := Scissors;
Put_Line ("P(Paper or Scissors) = Scissors");
Put ("P(");
Put (Integer (Paper), 0, 2);
Put (" or ");
Put (Integer (Scissors), 0, 2);
Put (") = P(");
Put (Integer (Paper or Scissors), 0, 2);
Put (") = ");
Put (Integer (P (Paper or Scissors)), 0, 2);
Put ("");
end;
结果
P(Paper or Scissors) = Scissors
P(2#10# or 2#100#) = P(2#110#) = 2#100#
使用枚举的解决方案
with Ada.Text_IO; use Ada.Text_IO;
with System;
with System.Unsigned_Types;
procedure Main is
type T is (Rock, Paper, Scissors, Suicide, None);
subtype S is System.Unsigned_Types.Unsigned range 0 .. 31;
use type S;
function B (Value : T) return S is (System.Unsigned_Types.Shift_Left (1, T'Pos (Value)));
function "&" (Left : T; Right : T) return S is (System.Unsigned_Types."or" (B (Left), B (Right)));
P : array (S) of T := (others => None);
begin
P (Rock & Paper) := Paper;
P (Rock & Scissors) := Rock;
P (Paper & Scissors) := Scissors;
Put_Line (T'Image (P (Rock & Paper)));
Put_Line (T'Image (P (Rock & Scissors)));
Put_Line (T'Image (P (Paper & Scissors)));
end;
结果
PAPER
ROCK
SCISSORS