From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on ip-172-31-65-14.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Ben Bacarisse Newsgroups: comp.lang.ada Subject: Re: project euler 26 Date: Wed, 06 Sep 2023 02:10:23 +0100 Organization: A noiseless patient Spider Message-ID: <87a5u0rts0.fsf@bsb.me.uk> References: <878r9mudvj.fsf@bsb.me.uk> <87a5u1u1yv.fsf@bsb.me.uk> <8734ztttpc.fsf@bsb.me.uk> <87fs3ssl6v.fsf@bsb.me.uk> MIME-Version: 1.0 Content-Type: text/plain Injection-Info: dont-email.me; posting-host="28c87aba986c3fbe6225b4a2a066932e"; logging-data="2312327"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+AbwzVclP68jBd4Z/+un/VveGZw7Lv02k=" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux) Cancel-Lock: sha1:UdmQdwiavArjukueY/hzb7WwWgw= sha1:cs0F/5BDWr6UlfTbt2WcA9C9AOM= X-BSB-Auth: 1.c8c19c3e65c6f903ca99.20230906021023BST.87a5u0rts0.fsf@bsb.me.uk Xref: news.eternal-september.org comp.lang.ada:65600 List-Id: "Dmitry A. Kazakov" writes: > On 2023-09-05 17:18, Ben Bacarisse wrote: > >> There was >> boiler plate code in my program that could be abstracted out into a >> generic function (or package?) so that any function can be maximised >> over some range or, better yet, any iterable type (if that's how Ada >> does things). > >> Can someone here show me how? > > You define some classes. Either generic or tagged. E.g. a generic class of > functions that uses two generic classes of the argument and the value: > > generic > -- Ordered argument > type Argument_Type is private; > with function Next (Value : Argument_Type) > return Argument_Type is <>; > with function "<" (Left, Right : Argument_Type) > return Boolean is <>; > with function "=" (Left, Right : Argument_Type) > return Boolean is <>; > -- Comparable value > type Value_Type is private; > with function "<" (Left, Right : Value_Type ) return Boolean is <>; > -- Function type > with function Func (Argument : Argument_Type) return Value_Type; > function Generic_Maximum_At (Left, Right : Argument_Type) > return Value_Type; > > and the implementation > > function Generic_Maximum_At (Left, Right : Argument_Type) > return Value_Type is > Argument : Argument_Type := Left; > Max : Value_Type; > Value : Value_Type; > begin > if Right < Left then > raise Constraint_Error with "Empty interval"; > end if; > Max := Func (Argument); > while not (Argument = Right) loop > Argument := Next (Argument); > Value := Func (Argument); > if Max < Value then > Max := Value; > end if; > end loop; > return Max; > end Generic_Maximum_At; > > or you can choose to pass the function as an argument: > > generic > -- Ordered argument > type Argument_Type is private; > with function Next (Value : Argument_Type) > return Argument_Type is <>; > with function "<" (Left, Right : Argument_Type) > return Boolean is <>; > -- Comparable value > type Value_Type is private; > with function "<" (Left, Right : Value_Type) return Boolean is <>; > function Generic_Maximum_At > ( Left, Right : Argument_Type; > Func : access function (Argument : Argument_Type) > return Value_Type > ) return Value_Type; > > Or you can make it a package which is usually a better choice as one can > pack into it several entities sharing the same generic interface: > > generic > -- Ordered argument > type Argument_Type is private; > with function Next (Value : Argument_Type) > return Argument_Type is <>; > with function "<" (Left, Right : Argument_Type ) > return Boolean is <>; > with function "=" (Left, Right : Argument_Type) > return Boolean is <>; > -- Comparable value > type Value_Type is private; > with function "<" (Left, Right : Value_Type) return Boolean is <>; > package Generic_Discrete_Comparable_Valued is > function Maximum_At > ( Left, Right : Argument_Type; > Func : access function (Argument : Argument_Type) > return Value_Type > ) return Value_Type; > -- Other useless functions > end Generic_Discrete_Comparable_Valued; > > The generic classes of arguments/values can be in turn factored out into > reusable generic packages: > > generic > -- Ordered argument > type Argument_Type is private; > with function Next (Value : Argument_Type) return Argument_Type is <>; > with function "<" (Left, Right : Argument_Type) return Boolean is <>; > with function "=" (Left, Right : Argument_Type) return Boolean is <>; > package Generic_Arguments is > end Generic_Arguments; > > generic > -- Comparable value > type Value_Type is private; > with function "<" (Left, Right : Value_Type ) return Boolean is <>; > package Generic_Values is > end Generic_Values; > > generic > with package Arguments is new Generic_Arguments (<>); > with package Values is new Generic_Values (<>); > package Generic_Discrete_Comparable_Valued is > use Arguments, Values; > function Maximum_At > ( Left, Right : Argument_Type; > Func : access function (Argument : Argument_Type) > return Value_Type > ) return Value_Type; > -- Other useless functions > end Generic_Discrete_Comparable_Valued; Thank you. I can't yet see how to use any of these alternatives, but that's my problem. Are there any good online sources on Ada generic programming so I can find out how to implement and use this short of package? -- Ben.