comp.lang.ada
 help / color / mirror / Atom feed
* Understanding generic package functions
@ 2015-11-03  0:45 Nick Gordon
  2015-11-03  3:36 ` Jeffrey R. Carter
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Nick Gordon @ 2015-11-03  0:45 UTC (permalink / raw)


Okay, basically I'm writing a demo of Ada for a class, and I'm trying to showcase Ada's math functions. This is the code:

   function Recoded_Exp(Power: in Float) return Float is -- Base e
      use Ada.Numerics.Generic_Elementary_Functions;
      use Ada.Numerics;
      ExpResult : Float;
   begin
      ExpResult := e ** Power;
      return ExpResult;
   end Recoded_Exp;

As you can see, what I'm trying to accomplish is confine the Float version of the "**" operator to this function, and I can't seem to do that, as well as use Ada's language-defined e constant. I've tried this by declaring the whole name, i.e. "Ada.Numerics.e Ada.Numerics.Generic_Elementary_Functions."**" Power", as well without the quotes enclosing the asterisks. Neither worked.

I've seen something that suggests I have to instantiate the generic package, but I don't understand how. For reference, the suggested approach is here:

with Square;
with Matrices;
procedure Matrix_Example is
  function Square_Matrix is new Square
    (Element_T => Matrices.Matrix_T, "*" => Matrices.Product);
  A : Matrices.Matrix_T := Matrices.Identity;
begin
  A := Square_Matrix (A);
end Matrix_Example;

My thought is that I have to create a new instance of the Generic_Elementary_Functions package, but I'm not sure if that's correct, or how to do that. In general, I'm noticing that the learning curve for Ada is steep, and there are not terribly many "quick references" for the language.

Nick

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Understanding generic package functions
  2015-11-03  0:45 Understanding generic package functions Nick Gordon
@ 2015-11-03  3:36 ` Jeffrey R. Carter
  2015-11-03  6:59 ` Randy Brukardt
  2015-11-03  9:40 ` Stephen Leake
  2 siblings, 0 replies; 7+ messages in thread
From: Jeffrey R. Carter @ 2015-11-03  3:36 UTC (permalink / raw)


On 11/02/2015 05:45 PM, Nick Gordon wrote:
> 
> My thought is that I have to create a new instance of the
> Generic_Elementary_Functions package, but I'm not sure if that's correct, or
> how to do that. In general, I'm noticing that the learning curve for Ada is
> steep, and there are not terribly many "quick references" for the language.

Generics exist for reuse. For example, Ada.Numerics.Generic_Elementary_Functions
allows the reuse of its algorithms with numerous floating-point types. You
create an instance of the generic package for a specific floating-point types
through the process of instantiation. You can think of a generic as a template
and instantiation in terms of macro expansion; you end up with a package with
the name of the instantiation and every occurrence of the generic formal
parameters replaced with the corresponding actual parameters from the
instantiation. (This isn't exactly correct but is close enough for most people,
especially for a beginner.) For example:

package Math is new Ada.Numerics.Generic_Elementary_Functions
   (Float_Type => Float);

Now you have a package named Math with functions that operate on type Float:

F : Float := Math.Sqrt (Ada.Numerics.e);

If you define your own floating-point type

type Big is digits System.Max_Digits;

you can instantiate Generic_Elementary_Functions for it, too

package Big_Math is new Ada.Numerics.Generic_Elementary_Functions
(Float_Type => Big);

-- 
Jeff Carter
"[T]he [Agile] idea that it's bad to spend an
appropriate time at the beginning of the project
to clarify the overall requirements and design
is nonsense."
Bertrand Meyer
149


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Understanding generic package functions
  2015-11-03  0:45 Understanding generic package functions Nick Gordon
  2015-11-03  3:36 ` Jeffrey R. Carter
@ 2015-11-03  6:59 ` Randy Brukardt
  2015-11-03  7:59   ` Nick Gordon
  2015-11-03  9:40 ` Stephen Leake
  2 siblings, 1 reply; 7+ messages in thread
From: Randy Brukardt @ 2015-11-03  6:59 UTC (permalink / raw)



"Nick Gordon" <annihilan@gmail.com> wrote in message 
news:cb181260-a5d3-4b5b-9a40-c925f7100b93@googlegroups.com...
...
> My thought is that I have to create a new instance of the 
> Generic_Elementary_Functions
> package, but I'm not sure if that's correct, or how to do that.

Jeff gave you the long answer, which is better for most purposes. 
Specifically for type Float (which you really should avoid itself, 
preferring to use types of your own definition), Ada offers a 
pre-instantiated version of the package called 
"Ada.Numerics.Elementary_Functions", so you could use that instead.

> In general, I'm noticing that the learning curve for Ada is steep, and 
> there are not
> terribly many "quick references" for the language.

Ada Distilled is the best "quick reference", but there's really nothing 
quick about using Ada. It's a professional level tool and thus it has lots 
of things that you need to know. (Consider the difference between using a 
home copy machine and a professional offset printing press.)

                                   Randy.



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Understanding generic package functions
  2015-11-03  6:59 ` Randy Brukardt
@ 2015-11-03  7:59   ` Nick Gordon
  2015-11-03  9:15     ` briot.emmanuel
  2015-11-03 17:27     ` Jeffrey R. Carter
  0 siblings, 2 replies; 7+ messages in thread
From: Nick Gordon @ 2015-11-03  7:59 UTC (permalink / raw)


On Monday, November 2, 2015 at 9:36:45 PM UTC-6, Jeffrey R. Carter wrote:
> On 11/02/2015 05:45 PM, Nick Gordon wrote:
> > 
> > My thought is that I have to create a new instance of the
> > Generic_Elementary_Functions package, but I'm not sure if that's correct, or
> > how to do that. In general, I'm noticing that the learning curve for Ada is
> > steep, and there are not terribly many "quick references" for the language.
> 
> Generics exist for reuse. For example, Ada.Numerics.Generic_Elementary_Functions
> allows the reuse of its algorithms with numerous floating-point types. You
> create an instance of the generic package for a specific floating-point types
> through the process of instantiation. You can think of a generic as a template
> and instantiation in terms of macro expansion; you end up with a package with
> the name of the instantiation and every occurrence of the generic formal
> parameters replaced with the corresponding actual parameters from the
> instantiation. (This isn't exactly correct but is close enough for most people,
> especially for a beginner.) For example:
> 
> package Math is new Ada.Numerics.Generic_Elementary_Functions
>    (Float_Type => Float);
> 
> Now you have a package named Math with functions that operate on type Float:
> 
> F : Float := Math.Sqrt (Ada.Numerics.e);
> 
> If you define your own floating-point type
> 
> type Big is digits System.Max_Digits;
> 
> you can instantiate Generic_Elementary_Functions for it, too
> 
> package Big_Math is new Ada.Numerics.Generic_Elementary_Functions
> (Float_Type => Big);
> 
> -- 
> Jeff Carter
> "[T]he [Agile] idea that it's bad to spend an
> appropriate time at the beginning of the project
> to clarify the overall requirements and design
> is nonsense."
> Bertrand Meyer
> 149

Oh! I see! Suddenly this makes much more sense. I appreciate this a lot! I see that it wasn't the declaration of Ada.Numerics.e that was the issue, but the generic package. How though do I use the overridden binary operator ** in that case? Do I call X MyPack."**" Y or is there some way for me to inform the compiler do it, like use MyPack;?

On Tuesday, November 3, 2015 at 12:59:35 AM UTC-6, Randy Brukardt wrote:
> "Nick Gordon" <annihilan@gmail.com> wrote in message 
> news:cb181260-a5d3-4b5b-9a40-c925f7100b93@googlegroups.com...
> ...
> > My thought is that I have to create a new instance of the 
> > Generic_Elementary_Functions
> > package, but I'm not sure if that's correct, or how to do that.
> 
> Jeff gave you the long answer, which is better for most purposes. 
> Specifically for type Float (which you really should avoid itself, 
> preferring to use types of your own definition), Ada offers a 
> pre-instantiated version of the package called 
> "Ada.Numerics.Elementary_Functions", so you could use that instead.
> 
> > In general, I'm noticing that the learning curve for Ada is steep, and 
> > there are not
> > terribly many "quick references" for the language.
> 
> Ada Distilled is the best "quick reference", but there's really nothing 
> quick about using Ada. It's a professional level tool and thus it has lots 
> of things that you need to know. (Consider the difference between using a 
> home copy machine and a professional offset printing press.)
> 
>                                    Randy.

For better or worse, I've just ordered for $10 total two of the books listed in the adaic.org's "learning resources" section, so I'm hoping that they will be a better learning tool than Ada Distilled, which I already have. Again, thanks to the both of you.

Nick

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Understanding generic package functions
  2015-11-03  7:59   ` Nick Gordon
@ 2015-11-03  9:15     ` briot.emmanuel
  2015-11-03 17:27     ` Jeffrey R. Carter
  1 sibling, 0 replies; 7+ messages in thread
From: briot.emmanuel @ 2015-11-03  9:15 UTC (permalink / raw)



One you have instantiated the Math package, as suggested by Jeffrey, you need to add a "use" clause for it:

    use Math;

At this point, "**" becomes visible. Your use clause on Ada.Numerics does not play that role.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Understanding generic package functions
  2015-11-03  0:45 Understanding generic package functions Nick Gordon
  2015-11-03  3:36 ` Jeffrey R. Carter
  2015-11-03  6:59 ` Randy Brukardt
@ 2015-11-03  9:40 ` Stephen Leake
  2 siblings, 0 replies; 7+ messages in thread
From: Stephen Leake @ 2015-11-03  9:40 UTC (permalink / raw)


Nick Gordon <annihilan@gmail.com> writes:

> Okay, basically I'm writing a demo of Ada for a class, and I'm trying
> to showcase Ada's math functions. 

Is this a class on Ada, or something else?

> This is the code:
>
>    function Recoded_Exp(Power: in Float) return Float is -- Base e
>       use Ada.Numerics.Generic_Elementary_Functions;
>       use Ada.Numerics;
>       ExpResult : Float;
>    begin
>       ExpResult := e ** Power;
>       return ExpResult;
>    end Recoded_Exp;

Style notes: it's best not to use "use" unless it really cleans up the
code (my rule is "unless the name is used at least three times"), and
not to define a local variable unless it is really needed.

> I've seen something that suggests I have to instantiate the generic
> package, but I don't understand how.

This is how:

with Ada.Numerics.Generic_Elementary_Functions;
function Recoded_Exp(Power: in Float) return Float is -- Base e
   package Float_Elementary is new Ada.Numerics.Generic_Elementary_Functions
     (Float_Type => Float);
   use Float_Elementary;
begin
   return Ada.Numerics.e ** Power;
end Recoded_Exp;

"Instantiating a generic package" means declaring a package using a
generic template instead of providing all the code directly. So this
line:

   package Float_Elementary is new Ada.Numerics.Generic_Elementary_Functions
     (Float_Type => Float);

declares the package "Float_Elementary", using the code from
Generic_Elementary_Functions, with "Float_Type" replaced by "Float".

-- 
-- Stephe

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Understanding generic package functions
  2015-11-03  7:59   ` Nick Gordon
  2015-11-03  9:15     ` briot.emmanuel
@ 2015-11-03 17:27     ` Jeffrey R. Carter
  1 sibling, 0 replies; 7+ messages in thread
From: Jeffrey R. Carter @ 2015-11-03 17:27 UTC (permalink / raw)


On 11/03/2015 12:59 AM, Nick Gordon wrote:
> 
> Oh! I see! Suddenly this makes much more sense. I appreciate this a lot! I
> see that it wasn't the declaration of Ada.Numerics.e that was the issue, but
> the generic package. How though do I use the overridden binary operator ** in
> that case? Do I call X MyPack."**" Y or is there some way for me to inform
> the compiler do it, like use MyPack;?

You have a number of options.

1. Full dotted name. An operator is a function just like any other function, and
can be called just like any other function:

Math."**" (X, Y)

2. Renaming.

function "**" (Left : Float; Right : Float) return Float renames Math."**";

This lets you use "**" as an infix operator: X ** Y

3. A use clause.

use Math;

This also lets you use "**" as an infix operator: X ** Y

The use clause gives you direct visibility to everything in the public part of
the pkg spec. Sometimes that's not desirable. I tend to avoid use clauses, since
they often make code harder to understand. I won't object too much for pkgs in
the standard library or for a limited scope with lots of references.

Not applicable in this case, but when a package declares a type and operations
on the type, you can use a "use type" clause

use [all] type Package_Name.Type_Name;

This gives direct visibility to the operators for Type_Name but not for anything
else in the pkg. If "all" is included, it makes some other things directly
visible, too, of which enumeration literals are the most commonly used.

-- 
Jeff Carter
"Drown in a vat of whiskey. Death, where is thy sting?"
Never Give a Sucker an Even Break
106

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-11-03 17:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-03  0:45 Understanding generic package functions Nick Gordon
2015-11-03  3:36 ` Jeffrey R. Carter
2015-11-03  6:59 ` Randy Brukardt
2015-11-03  7:59   ` Nick Gordon
2015-11-03  9:15     ` briot.emmanuel
2015-11-03 17:27     ` Jeffrey R. Carter
2015-11-03  9:40 ` Stephen Leake

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox