1 1 © adacore under the gnu free documentation license franco gasperoni [email protected]
TRANSCRIPT
11http://libre.adacore.com © AdaCore under the GNU Free Documentation License
Franco Gasperoni
http://libre.adacore.com
33http://libre.adacore.com © AdaCore under the GNU Free Documentation License
44http://libre.adacore.com © AdaCore under the GNU Free Documentation License
We often write similar code...We often write similar code...procedure Swap (X, Y : in out IntegerInteger) is Tmp : Integer Integer := X;begin X := Y; Y := Tmp;end
procedure Swap (X, Y : in out IntegerInteger) is Tmp : Integer Integer := X;begin X := Y; Y := Tmp;end
procedure Swap (X, Y : in out FloatFloat) is Tmp : FloatFloat := X;begin X := Y; Y := Tmp;end
procedure Swap (X, Y : in out FloatFloat) is Tmp : FloatFloat := X;begin X := Y; Y := Tmp;end
55http://libre.adacore.com © AdaCore under the GNU Free Documentation License
This is...This is...
• Time consuming
• Error prone (cut & paste)
• Maintenance hazard
66http://libre.adacore.com © AdaCore under the GNU Free Documentation License
Genericity allows you to Genericity allows you to parameterize your codeparameterize your code
generic type Some_TypeSome_Type is private;procedure Gen_Swap (X, Y : in out Some_TypeSome_Type);
generic type Some_TypeSome_Type is private;procedure Gen_Swap (X, Y : in out Some_TypeSome_Type);
Any non limited type without discriminantsAny non limited type without discriminantsgen_swap.ads
procedure Gen_Swap (X, Y : in out Some_TypeSome_Type) is Tmp : Some_Type Some_Type := X;begin X := Y; Y := Tmp;end Gen_Swap;
procedure Gen_Swap (X, Y : in out Some_TypeSome_Type) is Tmp : Some_Type Some_Type := X;begin X := Y; Y := Tmp;end Gen_Swap;
gen_swap.adb
77http://libre.adacore.com © AdaCore under the GNU Free Documentation License
Instantiating a GenericInstantiating a Generic
with Gen_Swap;procedure Client is
procedure Swap is new Gen_Swap (Some_Type => Integer); procedure Swap is new Gen_Swap (Some_Type => Float);
A, B : Integer := …; P, Q : Float := …;
begin Swap (A, B); Swap (P, Q);end Swap;
with Gen_Swap;procedure Client is
procedure Swap is new Gen_Swap (Some_Type => Integer); procedure Swap is new Gen_Swap (Some_Type => Float);
A, B : Integer := …; P, Q : Float := …;
begin Swap (A, B); Swap (P, Q);end Swap;
Generic instantiationGeneric instantiation
88http://libre.adacore.com © AdaCore under the GNU Free Documentation License
Type of Generic UnitsType of Generic Units
generic … formal parameters ...procedure Proc (…);
generic … formal parameters ...procedure Proc (…);
generic … formal parameters ...function Func (…) return …;
generic … formal parameters ...function Func (…) return …;
generic … formal parameters ...package Pack is … end Pack;
generic … formal parameters ...package Pack is … end Pack;
99http://libre.adacore.com © AdaCore under the GNU Free Documentation License
… … formal parameters ...formal parameters ...
• Types
• Objects
• Subprograms
• Packages
1010http://libre.adacore.com © AdaCore under the GNU Free Documentation License
Another exampleAnother example
Write a generic function that computes
where
L & H are integer bounds
F is some function returning some type
An addition operation is available for this type
H
Li
iFHLSum )(),(
H
Li
iFHLSum )(),(
1111http://libre.adacore.com © AdaCore under the GNU Free Documentation License
generic type Res_Type is private;
Zero : in Res_Type;
with function Add (X, Y : Res_Type) return Res_Type; with function F (I : Integer) return Res_Type;
function Sum (L, H : Integer) return Res_Type;
generic type Res_Type is private;
Zero : in Res_Type;
with function Add (X, Y : Res_Type) return Res_Type; with function F (I : Integer) return Res_Type;
function Sum (L, H : Integer) return Res_Type;
Spec ...Spec ...
1212http://libre.adacore.com © AdaCore under the GNU Free Documentation License
function Sum (L, H : Integer) return Res_Type is Result : Res_Type := Zero;
begin for I in L .. H loop Result := Add (Result, F (I)); end loop;
return Result;end Sum;
function Sum (L, H : Integer) return Res_Type is Result : Res_Type := Zero;
begin for I in L .. H loop Result := Add (Result, F (I)); end loop;
return Result;end Sum;
Body ...Body ...
1313http://libre.adacore.com © AdaCore under the GNU Free Documentation License
with Sum;procedure Client is function Compute (X : Integer) return Integer is … end; function Compute (X : Integer) return Float is … end;
function New_Sum is new Sum (Res_Type => Integer, Zero => 0, Add => “+”, F => Compute);
function New_Sum is new Sum (Res_Type => Float, Zero => 0.0, Add => “+”, F => Compute);
with Sum;procedure Client is function Compute (X : Integer) return Integer is … end; function Compute (X : Integer) return Float is … end;
function New_Sum is new Sum (Res_Type => Integer, Zero => 0, Add => “+”, F => Compute);
function New_Sum is new Sum (Res_Type => Float, Zero => 0.0, Add => “+”, F => Compute);
Instantiating SumInstantiating Sum
1414http://libre.adacore.com © AdaCore under the GNU Free Documentation License
generic type Res_Type is private;
Zero : in Res_Type;
with function Add (X, Y : Res_Type) return Res_Type; with function F (I : Integer) return Res_Type is <>;
function Sum (L, H : Integer) return Res_Type;
generic type Res_Type is private;
Zero : in Res_Type;
with function Add (X, Y : Res_Type) return Res_Type; with function F (I : Integer) return Res_Type is <>;
function Sum (L, H : Integer) return Res_Type;
Default Generic ParametersDefault Generic Parameters
1515http://libre.adacore.com © AdaCore under the GNU Free Documentation License
with Sum;procedure Client is function F (X : Integer) return Integer is … end; function F (X : Integer) return Float is … end;
function New_Sum is new Sum (Res_Type => Integer, Zero => 0, Add => “+”);
function New_Sum is new Sum (Res_Type => Float, Zero => 0.0, Add => “+”);
with Sum;procedure Client is function F (X : Integer) return Integer is … end; function F (X : Integer) return Float is … end;
function New_Sum is new Sum (Res_Type => Integer, Zero => 0, Add => “+”);
function New_Sum is new Sum (Res_Type => Float, Zero => 0.0, Add => “+”);
You can omit You can omit F => FF => F
You can omit parameter F if there is a visibleroutine called F with the right parameters You can omit parameter F if there is a visibleroutine called F with the right parameters
1616http://libre.adacore.com © AdaCore under the GNU Free Documentation License
Allowed to use Allowed to use “+” “-” ““+” “-” “**” etc.” etc.
as function namesas function names
package Sets is type Set is private;
Empty : constant Set; function “+” (S1, S2 : Set) return Set; -- Set union function “*” (S1, S2 : Set) return Set; -- Set intersection function “-” (S1, S2 : Set) return Set; -- Set difference … private type Set is …;end Alerts;
package Sets is type Set is private;
Empty : constant Set; function “+” (S1, S2 : Set) return Set; -- Set union function “*” (S1, S2 : Set) return Set; -- Set intersection function “-” (S1, S2 : Set) return Set; -- Set difference … private type Set is …;end Alerts;
1717http://libre.adacore.com © AdaCore under the GNU Free Documentation License
Back to our Generic SumBack to our Generic Sum
generic type Res_Type is private;
Zero : in Res_Type;
with function “+” (X, Y : Res_Type) return Res_Type is <>; with function F (I : Integer) return Res_Type is <>;
function Sum (L, H : Integer) return Res_Type;
generic type Res_Type is private;
Zero : in Res_Type;
with function “+” (X, Y : Res_Type) return Res_Type is <>; with function F (I : Integer) return Res_Type is <>;
function Sum (L, H : Integer) return Res_Type;
1818http://libre.adacore.com © AdaCore under the GNU Free Documentation License
function Sum (L, H : Integer) return Res_Type is Result : Res_Type := Zero;
begin for I in L .. H loop Result := Result + F (I); end loop;
return Result;end Sum;
function Sum (L, H : Integer) return Res_Type is Result : Res_Type := Zero;
begin for I in L .. H loop Result := Result + F (I); end loop;
return Result;end Sum;
Body ...Body ...
1919http://libre.adacore.com © AdaCore under the GNU Free Documentation License
with Sum;with Sets; use Sets;procedure Client is function F (X : Integer) return Integer is … end; function F (X : Integer) return Set is … end;
function New_Sum is new Sum (Res_Type => Integer, Zero => 0);
function New_Sum is new Sum (Res_Type => Set, Zero => Empty);
with Sum;with Sets; use Sets;procedure Client is function F (X : Integer) return Integer is … end; function F (X : Integer) return Set is … end;
function New_Sum is new Sum (Res_Type => Integer, Zero => 0);
function New_Sum is new Sum (Res_Type => Set, Zero => Empty);
You can omit You can omit F => F F => F and and “+” => “+”“+” => “+”