comp.lang.ada
 help / color / mirror / Atom feed
* Instantiating package problems
@ 2016-01-03 18:40 Andrew Shvets
  2016-01-03 20:27 ` Georg Bauhaus
                   ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: Andrew Shvets @ 2016-01-03 18:40 UTC (permalink / raw)


Hi all,

This is coming from the perspective of someone that has far more C++ OOP experience.  Basically, what I'm trying to do is create an instance of a package and then call a function from that object.  This is what I have below.  The calculator package is a simple package with the Addition function (which, you guessed it, just adds numbers together) that takes two integers and returns an integer.

I think I'm not quite getting this right or I've misunderstood something.  Here is my code so far and the results that I get when I compile it.

=========================================================
with Ada.Text_IO;

with Calculator;

procedure Main is
  Calc : Calculator;
begin
  ...

  Ada.Text_IO.Put_Line(" Addition:       " & Integer'Image(Calc.Addition(52, 31)));
  Ada.Text_IO.New_Line;
end Main;

OUTPUT:$ gnatmake -g main.adb calculator.adb
gcc -c -g main.adb
main.adb:10:10: subtype mark required in this context
main.adb:10:10: found "calculator" declared at calculator.ads:5
main.adb:22:60: invalid prefix in selected component "Calc"
gnatmake: "main.adb" compilation error
=========================================================

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

* Re: Instantiating package problems
  2016-01-03 18:40 Instantiating package problems Andrew Shvets
@ 2016-01-03 20:27 ` Georg Bauhaus
  2016-01-03 21:21   ` Andrew Shvets
  2016-01-03 21:04 ` Jeffrey R. Carter
  2016-01-03 22:08 ` Bob Duff
  2 siblings, 1 reply; 34+ messages in thread
From: Georg Bauhaus @ 2016-01-03 20:27 UTC (permalink / raw)


On 03.01.16 19:40, Andrew Shvets wrote:
> Hi all,
>
> This is coming from the perspective of someone that has far more C++ OOP experience.  Basically, what I'm trying to do is create an instance of a package and then call a function from that object.  This is what I have below.  The calculator package is a simple package with the Addition function (which, you guessed it, just adds numbers together) that takes two integers and returns an integer.

The C++ equivalent of a generic package of Ada would be

(a) a generic namespace (with an optional block of statements
that are executed when the namespace is elaborated), or

(b) a generic file that has, alongside any definitions, also said block
of statements.

C++ is different from Ada in this regard, since it has generic types
only and none of the above, except for preprocessor tricks.
Ada, OTOH, does not have generic types, only generic units (possibly
containing types) such as packages and subprograms.

"Calculator" of your example names a package, but not a (sub)type,
this is what the compiler says in its first message.

If it is a generic package, then you'd be instantiating packages
from it, but not objects. Again, unlike C++, which provides for
some automatically inferred instantiations, Ada requires that
generic units be instantiated explicitly.

> OUTPUT:$ gnatmake -g main.adb calculator.adb
> gcc -c -g main.adb
> main.adb:10:10: subtype mark required in this context
> main.adb:10:10: found "calculator" declared at calculator.ads:5
> main.adb:22:60: invalid prefix in selected component "Calc"
> gnatmake: "main.adb" compilation error
> =========================================================
>


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

* Re: Instantiating package problems
  2016-01-03 18:40 Instantiating package problems Andrew Shvets
  2016-01-03 20:27 ` Georg Bauhaus
@ 2016-01-03 21:04 ` Jeffrey R. Carter
  2016-01-03 21:27   ` Andrew Shvets
  2016-01-03 22:08 ` Bob Duff
  2 siblings, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2016-01-03 21:04 UTC (permalink / raw)


On 01/03/2016 11:40 AM, Andrew Shvets wrote:
> 
> This is coming from the perspective of someone that has far more C++ OOP
> experience.  Basically, what I'm trying to do is create an instance of a
> package and then call a function from that object.  This is what I have
> below.  The calculator package is a simple package with the Addition function
> (which, you guessed it, just adds numbers together) that takes two integers
> and returns an integer.

First you need to unlearn everything you've learned from using a poorly
designed, error-prone language.

"Instantiate" in Ada is a technical term that refers to creating a package or
subprogram from a generic. There don't appear to be any generics in your
example, so your subject line is a bit misleading.

You haven't shown us Calculator, so we can't be sure what you're trying to do,
but I'm going to guess that it looks like

package Calculator is
   function Addition (Left : Integer; Right : Integer) return Integer;
end Calculator;

If I'm wrong, then you can probably ignore everything else I'm going to say.

A pkg is a module. It provides encapsulation and information hiding. C++ doesn't
have modules, which are an essential part of any language. A pkg is not a
(sub)type, so you can't declare objects of it. A pkg just is. Once you say

with Calculator;

you have Calculator and you can refer to it, just like Ada.Text_IO. What you're
probably trying to do is

with Ada.Text_IO;
with Calculator;

procedure Test_Calculator is
   -- The declarative part is empty, since no declarations are needed
begin -- Test_Calculator
   Ada.Text_IO.Put_Line
      (Item => "Addition (52, 31): " &
               Integer'Image (Calculator.Addition (52, 31) ) );
end Test_Calculator;

-- 
Jeff Carter
"Who wears beige to a bank robbery?"
Take the Money and Run
144


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

* Re: Instantiating package problems
  2016-01-03 20:27 ` Georg Bauhaus
@ 2016-01-03 21:21   ` Andrew Shvets
  0 siblings, 0 replies; 34+ messages in thread
From: Andrew Shvets @ 2016-01-03 21:21 UTC (permalink / raw)


Ok, so basically, my way of thinking about OOP in Ada is flawed.  All packages, by default, are static (as well as their methods), but if I want to call a method (procedure/function) I would have to do this on a type that's inside of a package, yes?

On Sunday, January 3, 2016 at 3:27:29 PM UTC-5, Georg Bauhaus wrote:
> On 03.01.16 19:40, Andrew Shvets wrote:
> > Hi all,
> >
> > This is coming from the perspective of someone that has far more C++ OOP experience.  Basically, what I'm trying to do is create an instance of a package and then call a function from that object.  This is what I have below.  The calculator package is a simple package with the Addition function (which, you guessed it, just adds numbers together) that takes two integers and returns an integer.
> 
> The C++ equivalent of a generic package of Ada would be
> 
> (a) a generic namespace (with an optional block of statements
> that are executed when the namespace is elaborated), or
> 
> (b) a generic file that has, alongside any definitions, also said block
> of statements.
> 
> C++ is different from Ada in this regard, since it has generic types
> only and none of the above, except for preprocessor tricks.
> Ada, OTOH, does not have generic types, only generic units (possibly
> containing types) such as packages and subprograms.
> 
> "Calculator" of your example names a package, but not a (sub)type,
> this is what the compiler says in its first message.
> 
> If it is a generic package, then you'd be instantiating packages
> from it, but not objects. Again, unlike C++, which provides for
> some automatically inferred instantiations, Ada requires that
> generic units be instantiated explicitly.
> 
> > OUTPUT:$ gnatmake -g main.adb calculator.adb
> > gcc -c -g main.adb
> > main.adb:10:10: subtype mark required in this context
> > main.adb:10:10: found "calculator" declared at calculator.ads:5
> > main.adb:22:60: invalid prefix in selected component "Calc"
> > gnatmake: "main.adb" compilation error
> > =========================================================
> >


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

* Re: Instantiating package problems
  2016-01-03 21:04 ` Jeffrey R. Carter
@ 2016-01-03 21:27   ` Andrew Shvets
  2016-01-03 22:39     ` Jeffrey R. Carter
  0 siblings, 1 reply; 34+ messages in thread
From: Andrew Shvets @ 2016-01-03 21:27 UTC (permalink / raw)


On Sunday, January 3, 2016 at 4:04:16 PM UTC-5, Jeffrey R. Carter wrote:
> On 01/03/2016 11:40 AM, Andrew Shvets wrote:
> > 
> > This is coming from the perspective of someone that has far more C++ OOP
> > experience.  Basically, what I'm trying to do is create an instance of a
> > package and then call a function from that object.  This is what I have
> > below.  The calculator package is a simple package with the Addition function
> > (which, you guessed it, just adds numbers together) that takes two integers
> > and returns an integer.
> 
> First you need to unlearn everything you've learned from using a poorly
> designed, error-prone language.
> 
> "Instantiate" in Ada is a technical term that refers to creating a package or
> subprogram from a generic. There don't appear to be any generics in your
> example, so your subject line is a bit misleading.
> 
> You haven't shown us Calculator, so we can't be sure what you're trying to do,
> but I'm going to guess that it looks like
> 
> package Calculator is
>    function Addition (Left : Integer; Right : Integer) return Integer;
> end Calculator;
> 
> If I'm wrong, then you can probably ignore everything else I'm going to say.
> 
> A pkg is a module. It provides encapsulation and information hiding. C++ doesn't
> have modules, which are an essential part of any language. A pkg is not a
> (sub)type, so you can't declare objects of it. A pkg just is. Once you say
> 
> with Calculator;
> 
> you have Calculator and you can refer to it, just like Ada.Text_IO. What you're
> probably trying to do is
> 
> with Ada.Text_IO;
> with Calculator;
> 
> procedure Test_Calculator is
>    -- The declarative part is empty, since no declarations are needed
> begin -- Test_Calculator
>    Ada.Text_IO.Put_Line
>       (Item => "Addition (52, 31): " &
>                Integer'Image (Calculator.Addition (52, 31) ) );
> end Test_Calculator;
> 
> -- 
> Jeff Carter
> "Who wears beige to a bank robbery?"
> Take the Money and Run
> 144

Ok, I see, I think.  I suppose a better analogy is how in C you use #include "Some_File.h" and all of the contents of that file just come in and can be used readily, yes?

I'm still a little bit lost on the below example:
https://en.wikibooks.org/wiki/Ada_Programming/Object_Orientation#Derived_types

Basically, an instance of a type inside of a package is created and that is used to work on.

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

* Re: Instantiating package problems
  2016-01-03 18:40 Instantiating package problems Andrew Shvets
  2016-01-03 20:27 ` Georg Bauhaus
  2016-01-03 21:04 ` Jeffrey R. Carter
@ 2016-01-03 22:08 ` Bob Duff
  2016-01-04  0:07   ` Andrew Shvets
  2 siblings, 1 reply; 34+ messages in thread
From: Bob Duff @ 2016-01-03 22:08 UTC (permalink / raw)


Andrew Shvets <andrew.shvets@gmail.com> writes:

> This is coming from the perspective of someone that has far more C++ OOP
> experience.

Ada has "packages" and "types".  C++ combines these into one feature
(the "class").  I suspect that difference explains your confusion.

>...Basically, what I'm trying to do is create an instance of a
> package and then call a function from that object.

There's no such thing as an instance of a package in Ada.
An instance of a generic package (which is sort of like a C++ template)
is a package, not an object.  An instance of a type is
an object.

>...This is what I have below.
> The calculator package is a simple package with the Addition function (which,
> you guessed it, just adds numbers together) that takes two integers and returns
> an integer.
>
> I think I'm not quite getting this right or I've misunderstood something.  Here
> is my code so far and the results that I get when I compile it.
>
> =========================================================
> with Ada.Text_IO;
>
> with Calculator;
>
> procedure Main is
>   Calc : Calculator;

Better to show a complete example.

But anyway, Calculator is a package, not a type.
I think you can get rid of this line.
I'm guessing there are no types declared in Calculator.

> begin
>   ...
>
>   Ada.Text_IO.Put_Line(" Addition:       " & Integer'Image(Calc.Addition(52, 31)));

I think you can just call Calculator.Addition.  I can't be sure without
a complete example.

By the way, I don't see anything object-oriented in this example.
It looks like you're just trying to call a function that is declared
in a package -- no need to create any objects here.

>   Ada.Text_IO.New_Line;
> end Main;
>
> OUTPUT:$ gnatmake -g main.adb calculator.adb

You don't need to tell gnatmake all the files.  Just the main
procedure -- it can find all the other files that need to be
[re]compiled based on the "with"s (etc.).

- Bob


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

* Re: Instantiating package problems
  2016-01-03 21:27   ` Andrew Shvets
@ 2016-01-03 22:39     ` Jeffrey R. Carter
  0 siblings, 0 replies; 34+ messages in thread
From: Jeffrey R. Carter @ 2016-01-03 22:39 UTC (permalink / raw)


On 01/03/2016 02:27 PM, Andrew Shvets wrote:
> 
> Ok, I see, I think.  I suppose a better analogy is how in C you use #include
> "Some_File.h" and all of the contents of that file just come in and can be
> used readily, yes?

Sort of. File inclusion is a clumsy process and makes everything equally
visible, so you end up with this.h having things named this_name so it won't
conflict with things named name from other headers. Ada's with only makes the
pkg directly visible, so you have to use dotted notation to references
declarations within the pkg.

You can make declarations within a pkg directly visible with a use clause. There
are times when it's a good idea to use "use", and times when it isn't. I
recommend that beginners avoid it completely.

> I'm still a little bit lost on the below example: 
> https://en.wikibooks.org/wiki/Ada_Programming/Object_Orientation#Derived_types

I recommend you avoid type extension until you understand the basics of the
language better. For experienced developers, I recommend /Ada Distilled/,
available from

http://www.adaic.org/learn/materials/

(directly from

http://www.adaic.org/wp-content/uploads/2010/05/Ada-Distilled-24-January-2011-Ada-2005-Version.pdf)

(I actually recommend that you avoid programming by extension completely, but if
you're going to do it, you should understand the language basics first, and
little is more basic about Ada than pkgs.)

-- 
Jeff Carter
"Who wears beige to a bank robbery?"
Take the Money and Run
144


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

* Re: Instantiating package problems
  2016-01-03 22:08 ` Bob Duff
@ 2016-01-04  0:07   ` Andrew Shvets
  2016-01-04  0:30     ` Andrew Shvets
  2016-01-04 20:49     ` Anh Vo
  0 siblings, 2 replies; 34+ messages in thread
From: Andrew Shvets @ 2016-01-04  0:07 UTC (permalink / raw)


Hi Bob,

Thanks for writing back.  This is the entire example:
http://pastebin.com/GEJT3WzL

Thanks for the tip on compiling.

On Sunday, January 3, 2016 at 5:08:53 PM UTC-5, Bob Duff wrote:
> Andrew Shvets <andre.....@gmail.com> writes:
> 
> > This is coming from the perspective of someone that has far more C++ OOP
> > experience.
> 
> Ada has "packages" and "types".  C++ combines these into one feature
> (the "class").  I suspect that difference explains your confusion.
> 
> >...Basically, what I'm trying to do is create an instance of a
> > package and then call a function from that object.
> 
> There's no such thing as an instance of a package in Ada.
> An instance of a generic package (which is sort of like a C++ template)
> is a package, not an object.  An instance of a type is
> an object.
> 
> >...This is what I have below.
> > The calculator package is a simple package with the Addition function (which,
> > you guessed it, just adds numbers together) that takes two integers and returns
> > an integer.
> >
> > I think I'm not quite getting this right or I've misunderstood something.  Here
> > is my code so far and the results that I get when I compile it.
> >
> > =========================================================
> > with Ada.Text_IO;
> >
> > with Calculator;
> >
> > procedure Main is
> >   Calc : Calculator;
> 
> Better to show a complete example.
> 
> But anyway, Calculator is a package, not a type.
> I think you can get rid of this line.
> I'm guessing there are no types declared in Calculator.
> 
> > begin
> >   ...
> >
> >   Ada.Text_IO.Put_Line(" Addition:       " & Integer'Image(Calc.Addition(52, 31)));
> 
> I think you can just call Calculator.Addition.  I can't be sure without
> a complete example.
> 
> By the way, I don't see anything object-oriented in this example.
> It looks like you're just trying to call a function that is declared
> in a package -- no need to create any objects here.
> 
> >   Ada.Text_IO.New_Line;
> > end Main;
> >
> > OUTPUT:$ gnatmake -g main.adb calculator.adb
> 
> You don't need to tell gnatmake all the files.  Just the main
> procedure -- it can find all the other files that need to be
> [re]compiled based on the "with"s (etc.).
> 
> - Bob


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

* Re: Instantiating package problems
  2016-01-04  0:07   ` Andrew Shvets
@ 2016-01-04  0:30     ` Andrew Shvets
  2016-01-04 13:43       ` G.B.
  2016-01-04 14:23       ` Brian Drummond
  2016-01-04 20:49     ` Anh Vo
  1 sibling, 2 replies; 34+ messages in thread
From: Andrew Shvets @ 2016-01-04  0:30 UTC (permalink / raw)


Ok, I think I understand.  In Ada, every vanilla package imports all of the public functions/procedures to be used and can be thought of as static functions in C++.  However, I can create instances of different records in order to retain an element of state like I would in C++ when I create an object.

Or am I completely off the rails?


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

* Re: Instantiating package problems
  2016-01-04  0:30     ` Andrew Shvets
@ 2016-01-04 13:43       ` G.B.
  2016-01-04 14:23       ` Brian Drummond
  1 sibling, 0 replies; 34+ messages in thread
From: G.B. @ 2016-01-04 13:43 UTC (permalink / raw)


On 04.01.16 01:30, Andrew Shvets wrote:
> Ok, I think I understand.  In Ada, every vanilla package imports all of the public functions/procedures to be used and can be thought of as static functions in C++.  However, I can create instances of different records in order to retain an element of state like I would in C++ when I create an object.
>

Consider this, just for some wording.

with Energy, Physics;

package Named_Things is

    function Consumption return Physics.Mass;
    -- equivalent of total energy transformed by traffic.

    type Car is private;

    procedure Method_1
      (The_Object : in out Car;
       Amount     : in     Energy.Fuel);

    function Method_2
      (The_Object : in Car)
      return Physics.Velocity;

    type Roadkill is
      (Squirrels, Cats, Rat, Opossums, Raccoons, Dogs, Deer);

    procedure Hit (Object_A : Roadkill; Object_B : Car);
    --  adds to goods consumed by traffic.

private

    Total_Consumption : Physics.Litres;
    --  burned by all cars, cf. Method_1, also equiv. Hit

    type Car is record
       Fill  : Energy.Fuel;
       -- ...
    end record;

end Named_Things;

Subprograms Method_1 and Method_2 belong to the primitive operations
of type Car, declared next to it as primitive subprograms. All three,
the type Car and its primitive subprograms, are declared in package
Named_Things.
Creating an object of type Car,

   My_Car : Named_Things.Car;

gives an instance of the type Car, for state;
calling Method_1 and passing this instance as the first argument
makes Method_1 operate on this object (formally, on the type, I think);
additionally, the body of Method_1 may assign a new value to the
variable Named_Things.Total_Consumption.

However, the package also has the declaration of another type
and two more procedures. One of them is referring to both types
in its parameter profile, viz. Hit.



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

* Re: Instantiating package problems
  2016-01-04  0:30     ` Andrew Shvets
  2016-01-04 13:43       ` G.B.
@ 2016-01-04 14:23       ` Brian Drummond
  1 sibling, 0 replies; 34+ messages in thread
From: Brian Drummond @ 2016-01-04 14:23 UTC (permalink / raw)


On Sun, 03 Jan 2016 16:30:02 -0800, Andrew Shvets wrote:

> Ok, I think I understand.  In Ada, every vanilla package imports all of
> the public functions/procedures to be used and can be thought of as
> static functions in C++.  



You're starting to get there.

You can't create an instance of a package, because a package already is 
an instance - like a C++ namespace rather than a C include. Then the 
variables, functions etc exported are "static" in C/C++ jargon. ("Static" 
has its own meanings in Ada and other non-C languages, it's advisable to 
be clear when you're using C-specific jargon).

(You CAN create an instance of a *generic* package, which is then an 
ordinary package. For example you could make Calculator generic on a 
numeric type, then create different instances of it with Integer or 
modular or floating point types giving FloatCalc.Addition for example.)

Being its own namespace, a package's functions can be used either as 
qualified names, Calculator.Addition, or made locally visible by "use 
Calculator" (cf C++ "using"). 

You can also use renames to simplify long (e.g.qualified) names, and 
operator overloading if you prefer to write C := A + B;


> However, I can create instances of different
> records in order to retain an element of state like I would in C++ when
> I create an object.

Almost right. As C++ classes are basically structs or unions, Ada uses 
the record as the basis for object oriented programming, by making it a 
"tagged record" where you want inheritance.

Record declarations, tagged or untagged, are type declarations, then you 
can declare instances of that record (objects).

But first : you don't need a record to give your package state. A package 
can contain variables, and even export them (declare them in the package 
specification). NB this is not good practice - it allows the package user 
to fiddle with the variable. Better to move the variable declaration into 
the "private part" or even the package body itself, and only allow access 
to it via approved methods.

As this means your application can only have one instance of this state, 
you may recognise the singleton pattern - an Ada singleton is simply a 
package.


But assuming you need multiple objects, you will declare and use records.
It's good practice to wrap a record declaration and all related 
subprograms in a package. You can keep the details of the record 
"private" so that users can't fiddle with its contents directly, only 
through subprograms in the same package. (I'm not providing samples - 
you'll find them easily enough once you grasp the basics, but just ask if 
you can't)

If you declare tagged records...
(1) you can later extend them, providing inheritance
type Derived is new Base with null record;
(2) although functions are declared with function(argument) notation, 
they can be called with either function(argument) or object.function 
notation.
(3) MyVar : Base; declares a variable holding a Base ONLY
MyVar : Base'Class; declares a variable holding a Base or any Derived 
type. This distinction is a key difference from most other OO languages.
(4) there are rules regarding primitive and despatching methods, allowing 
dynamic despatching where necessary but optimising it away otherwise.
(5) You can declare methods "overriding" or not, to catch certain types 
of error
(6) You have interfaces to provide a limited form of multiple 
inheritance, but not full MI.
(7) As with arrays, it's normal to handle (allocate a variable 
containing) the object itself, rather than an access (pointer) to it 
where possible. Access types with allocation impose the normal sorts of 
problems (albeit with stricter checks to limit them) but there are 
strategies to reduce the need for them : (a) Ada.Containers (like the C++ 
STL, which actually started life as an Ada project) (b) storage pools, 
which allow automatic release when the entire pool goes out of scope, (c) 
patterns for implementing various types of smart pointer.
(8) Constructors and destructors don't happen the same way. Think of Ada 
as adopting the Object Factory pattern, as a first approximation. BUT...
(9) If you need things to happen automatically on object creation, 
assignment, destruction, look at Controlled Types.

much more, but that's probably enough for now.

-- Brian


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

* Re: Instantiating package problems
  2016-01-04  0:07   ` Andrew Shvets
  2016-01-04  0:30     ` Andrew Shvets
@ 2016-01-04 20:49     ` Anh Vo
  2016-01-04 21:10       ` Dmitry A. Kazakov
                         ` (2 more replies)
  1 sibling, 3 replies; 34+ messages in thread
From: Anh Vo @ 2016-01-04 20:49 UTC (permalink / raw)


On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> Hi Bob,
> 
> Thanks for writing back.  This is the entire example:
> http://pastebin.com/GEJT3WzL
 
Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 

  function Division(
    Input1 : in Integer;
    Input2 : in Integer)
      return Integer
   with pre => Input2 /= 0;

Anh Vo

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

* Re: Instantiating package problems
  2016-01-04 20:49     ` Anh Vo
@ 2016-01-04 21:10       ` Dmitry A. Kazakov
  2016-01-04 22:39         ` Anh Vo
  2016-01-06  2:46       ` Andrew Shvets
  2016-01-06  3:30       ` Andrew Shvets
  2 siblings, 1 reply; 34+ messages in thread
From: Dmitry A. Kazakov @ 2016-01-04 21:10 UTC (permalink / raw)


On 2016-01-04 21:49, Anh Vo wrote:
> On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
>> Hi Bob,
>>
>> Thanks for writing back.  This is the entire example:
>> http://pastebin.com/GEJT3WzL
>
> Just recommend to add a precondition to function Division as shown below.
 > By the way, this feature is part of latest Ada (Ada 2012). In addition,
 > you should think about adding precondition to other operations such as
 > Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= 
Integer'Last.
>
>    function Division(
>      Input1 : in Integer;
>      Input2 : in Integer)
>        return Integer
>     with pre => Input2 /= 0;

The correct precondition of integer division is

    Input1/Input2 in Integer'Range

Note that it precludes zero divide, provided Ada 2012 can understand it, 
according to 3.5.4 (8) it must, but I am not a language lawer.

For a 2's complement machine the offending case is

    Input1 = Integer'First
    Input2 = -1

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Instantiating package problems
  2016-01-04 21:10       ` Dmitry A. Kazakov
@ 2016-01-04 22:39         ` Anh Vo
  2016-01-05  1:42           ` Anh Vo
  2016-01-05  7:35           ` Dmitry A. Kazakov
  0 siblings, 2 replies; 34+ messages in thread
From: Anh Vo @ 2016-01-04 22:39 UTC (permalink / raw)


On Monday, January 4, 2016 at 1:10:59 PM UTC-8, Dmitry A. Kazakov wrote:
> On 2016-01-04 21:49, Anh Vo wrote:
> > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> >> Hi Bob,
> >>
> >> Thanks for writing back.  This is the entire example:
> >> http://pastebin.com/GEJT3WzL
> >
> > Just recommend to add a precondition to function Division as shown below.
>  > By the way, this feature is part of latest Ada (Ada 2012). In addition,
>  > you should think about adding precondition to other operations such as
>  > Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= 
> Integer'Last.
> >
> >    function Division(
> >      Input1 : in Integer;
> >      Input2 : in Integer)
> >        return Integer
> >     with pre => Input2 /= 0;
> 
> The correct precondition of integer division is
> 
>     Input1/Input2 in Integer'Range
> 
> Note that it precludes zero divide, provided Ada 2012 can understand it, 
> according to 3.5.4 (8) it must, but I am not a language lawer.

Neither, I am a language lawyer. However, did not see paragraph LRM 3.5.4 (8) precluded zero divide for Integer type.
  
Anh Vo 


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

* Re: Instantiating package problems
  2016-01-04 22:39         ` Anh Vo
@ 2016-01-05  1:42           ` Anh Vo
  2016-01-05  7:35           ` Dmitry A. Kazakov
  1 sibling, 0 replies; 34+ messages in thread
From: Anh Vo @ 2016-01-05  1:42 UTC (permalink / raw)


On Monday, January 4, 2016 at 2:39:04 PM UTC-8, Anh Vo wrote:
> On Monday, January 4, 2016 at 1:10:59 PM UTC-8, Dmitry A. Kazakov wrote:
> > On 2016-01-04 21:49, Anh Vo wrote:
> > > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > >> Hi Bob,
> > >>
> > >> Thanks for writing back.  This is the entire example:
> > >> http://pastebin.com/GEJT3WzL
> > >
> > > Just recommend to add a precondition to function Division as shown below.
> >  > By the way, this feature is part of latest Ada (Ada 2012). In addition,
> >  > you should think about adding precondition to other operations such as
> >  > Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= 
> > Integer'Last.
> > >
> > >    function Division(
> > >      Input1 : in Integer;
> > >      Input2 : in Integer)
> > >        return Integer
> > >     with pre => Input2 /= 0;
> > 
> > The correct precondition of integer division is
> > 
> >     Input1/Input2 in Integer'Range
> > 
> > Note that it precludes zero divide, provided Ada 2012 can understand it, 
> > according to 3.5.4 (8) it must, but I am not a language lawer.
> 
> Neither, I am a language lawyer. However, did not see paragraph LRM 3.5.4 (8) precluded zero divide for Integer type.

Oops! There was an obvious typo. it supposed to read "However, I did not ... "
 


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

* Re: Instantiating package problems
  2016-01-04 22:39         ` Anh Vo
  2016-01-05  1:42           ` Anh Vo
@ 2016-01-05  7:35           ` Dmitry A. Kazakov
  1 sibling, 0 replies; 34+ messages in thread
From: Dmitry A. Kazakov @ 2016-01-05  7:35 UTC (permalink / raw)


On 2016-01-04 23:39, Anh Vo wrote:
> On Monday, January 4, 2016 at 1:10:59 PM UTC-8, Dmitry A. Kazakov wrote:

>> Note that it precludes zero divide, provided Ada 2012 can understand it,
>> according to 3.5.4 (8) it must, but I am not a language lawer.
>
> Neither, I am a language lawyer. However, did not see paragraph LRM 3.5.4 (8) precluded zero divide for Integer type.

3.5.4 (8) defines the set of integer values as Z. Since x/0 is not an 
integer value (Z) it is not in any range of, mathematically speaking...

Similarly 3.5.7 (8) means that Float'Range may not include NaN.

Though floating point operations are allowed to return NaN. That is why 
one needs lawyers!

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: Instantiating package problems
  2016-01-04 20:49     ` Anh Vo
  2016-01-04 21:10       ` Dmitry A. Kazakov
@ 2016-01-06  2:46       ` Andrew Shvets
  2016-01-06  8:53         ` Dmitry A. Kazakov
  2016-01-06  3:30       ` Andrew Shvets
  2 siblings, 1 reply; 34+ messages in thread
From: Andrew Shvets @ 2016-01-06  2:46 UTC (permalink / raw)


On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > Hi Bob,
> > 
> > Thanks for writing back.  This is the entire example:
> > http://pastebin.com/GEJT3WzL
>  
> Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> 
>   function Division(
>     Input1 : in Integer; 
>     Input2 : in Integer)
>       return Integer
>    with pre => Input2 /= 0;
> 
> Anh Vo

I have never heard of preconditions.  I'll definitely take a look.


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

* Re: Instantiating package problems
  2016-01-04 20:49     ` Anh Vo
  2016-01-04 21:10       ` Dmitry A. Kazakov
  2016-01-06  2:46       ` Andrew Shvets
@ 2016-01-06  3:30       ` Andrew Shvets
  2016-01-06  4:51         ` Anh Vo
  2 siblings, 1 reply; 34+ messages in thread
From: Andrew Shvets @ 2016-01-06  3:30 UTC (permalink / raw)


On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > Hi Bob,
> > 
> > Thanks for writing back.  This is the entire example:
> > http://pastebin.com/GEJT3WzL
>  
> Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> 
>   function Division(
>     Input1 : in Integer;
>     Input2 : in Integer)
>       return Integer
>    with pre => Input2 /= 0;
> 
> Anh Vo

I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:

....

 Division:        4


raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero

Shouldn't the division function been prevented from running the actual division operation beforehand?

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

* Re: Instantiating package problems
  2016-01-06  3:30       ` Andrew Shvets
@ 2016-01-06  4:51         ` Anh Vo
  2016-01-06  4:54           ` Anh Vo
                             ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: Anh Vo @ 2016-01-06  4:51 UTC (permalink / raw)


On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > > Hi Bob,
> > > 
> > > Thanks for writing back.  This is the entire example:
> > > http://pastebin.com/GEJT3WzL
> >  
> > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> > 
> >   function Division(
> >     Input1 : in Integer;
> >     Input2 : in Integer)
> >       return Integer
> >    with pre => Input2 /= 0;
> > 
> > Anh Vo
> 
> I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:
> 
> ....
> 
>  Division:        4
> 
> 
> raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> 
> Shouldn't the division function been prevented from running the actual division operation beforehand?

The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.


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

* Re: Instantiating package problems
  2016-01-06  4:51         ` Anh Vo
@ 2016-01-06  4:54           ` Anh Vo
  2016-01-06  5:00           ` Andrew Shvets
  2016-01-06 14:25           ` Bob Duff
  2 siblings, 0 replies; 34+ messages in thread
From: Anh Vo @ 2016-01-06  4:54 UTC (permalink / raw)


On Tuesday, January 5, 2016 at 8:52:00 PM UTC-8, Anh Vo wrote:
> On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> > On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> > > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > > > Hi Bob,
> > > > 
> > > > Thanks for writing back.  This is the entire example:
> > > > http://pastebin.com/GEJT3WzL
> > >  
> > > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> > > 
> > >   function Division(
> > >     Input1 : in Integer;
> > >     Input2 : in Integer)
> > >       return Integer
> > >    with pre => Input2 /= 0;
> > > 
> > > Anh Vo
> > 
> > I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:
> > 
> > ....
> > 
> >  Division:        4
> > 
> > 
> > raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> > 
> > Shouldn't the division function been prevented from running the actual division operation beforehand?
> 
> The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.

The call would be rejected off hand with ASSERTION_ERROR raised at the point of the call.


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

* Re: Instantiating package problems
  2016-01-06  4:51         ` Anh Vo
  2016-01-06  4:54           ` Anh Vo
@ 2016-01-06  5:00           ` Andrew Shvets
  2016-01-06  5:07             ` Anh Vo
  2016-01-06 13:07             ` G.B.
  2016-01-06 14:25           ` Bob Duff
  2 siblings, 2 replies; 34+ messages in thread
From: Andrew Shvets @ 2016-01-06  5:00 UTC (permalink / raw)


On Tuesday, January 5, 2016 at 11:52:00 PM UTC-5, Anh Vo wrote:
> On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> > On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> > > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > > > Hi Bob,
> > > > 
> > > > Thanks for writing back.  This is the entire example:
> > > > http://pastebin.com/GEJT3WzL
> > >  
> > > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> > > 
> > >   function Division(
> > >     Input1 : in Integer;
> > >     Input2 : in Integer)
> > >       return Integer
> > >    with pre => Input2 /= 0;
> > > 
> > > Anh Vo
> > 
> > I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:
> > 
> > ....
> > 
> >  Division:        4
> > 
> > 
> > raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> > 
> > Shouldn't the division function been prevented from running the actual division operation beforehand?
> 
> The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.

This is how the body looks like now:
http://pastebin.com/Mt0E0HAD

I'm still getting a constraint error.


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

* Re: Instantiating package problems
  2016-01-06  5:00           ` Andrew Shvets
@ 2016-01-06  5:07             ` Anh Vo
  2016-01-07  4:41               ` Andrew Shvets
  2016-01-06 13:07             ` G.B.
  1 sibling, 1 reply; 34+ messages in thread
From: Anh Vo @ 2016-01-06  5:07 UTC (permalink / raw)


On Tuesday, January 5, 2016 at 9:00:50 PM UTC-8, Andrew Shvets wrote:
> On Tuesday, January 5, 2016 at 11:52:00 PM UTC-5, Anh Vo wrote:
> > On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> > > On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> > > > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > > > > Hi Bob,
> > > > > 
> > > > > Thanks for writing back.  This is the entire example:
> > > > > http://pastebin.com/GEJT3WzL
> > > >  
> > > > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> > > > 
> > > >   function Division(
> > > >     Input1 : in Integer;
> > > >     Input2 : in Integer)
> > > >       return Integer
> > > >    with pre => Input2 /= 0;
> > > > 
> > > > Anh Vo
> > > 
> > > I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:
> > > 
> > > ....
> > > 
> > >  Division:        4
> > > 
> > > 
> > > raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> > > 
> > > Shouldn't the division function been prevented from running the actual division operation beforehand?
> > 
> > The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.
> 
> This is how the body looks like now:
> http://pastebin.com/Mt0E0HAD
> 
> I'm still getting a constraint error.

I only saw the pragma placed inside the package body. It should be placed in the package specification.


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

* Re: Instantiating package problems
  2016-01-06  2:46       ` Andrew Shvets
@ 2016-01-06  8:53         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 34+ messages in thread
From: Dmitry A. Kazakov @ 2016-01-06  8:53 UTC (permalink / raw)


On 2016-01-06 03:46, Andrew Shvets wrote:

> I have never heard of preconditions.  I'll definitely take a look.

Start with The Science of Programming by David Gries:

http://www.amazon.com/The-Science-Programming-Monographs-Computer/dp/0387964800

(I believe free PDF copies to download is available as well, though I 
don't know how legal they are)

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Instantiating package problems
  2016-01-06  5:00           ` Andrew Shvets
  2016-01-06  5:07             ` Anh Vo
@ 2016-01-06 13:07             ` G.B.
  2016-01-07  4:42               ` Andrew Shvets
  1 sibling, 1 reply; 34+ messages in thread
From: G.B. @ 2016-01-06 13:07 UTC (permalink / raw)


On 06.01.16 06:00, Andrew Shvets wrote:
> On Tuesday, January 5, 2016 at 11:52:00 PM UTC-5, Anh Vo wrote:

>> The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.
>
> This is how the body looks like now:
> http://pastebin.com/Mt0E0HAD
>
> I'm still getting a constraint error.
>

You should see something like this, after adding Assertion_Policy
in the way Anh Vo has described:

raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from 
shvets.ada:15

If you know that what Dmitry has explained is true,
you could state it as a workable approximation,
so that clients of the package know what to do when
the programmers are not certain about all implications,
practical and theoretical, of predefined division "/"
in Input1/Input2, Integer'[Base']Range, and more:


    Extra_Value : constant Boolean :=
      not (Integer'Last = -Integer'First);

    function Division
      (Input1 : in Integer;
       Input2 : in Integer)
      return Integer
    with
      Pre =>
        Input2 /= 0
        and
        (if Extra_Value
         then not (Input1 = Integer'First and Input2 = -1)),
      Post =>
        Input1/Input2 in Integer'Range
        and
        Division'Result = Input1/Input2;

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

* Re: Instantiating package problems
  2016-01-06  4:51         ` Anh Vo
  2016-01-06  4:54           ` Anh Vo
  2016-01-06  5:00           ` Andrew Shvets
@ 2016-01-06 14:25           ` Bob Duff
  2016-01-06 23:48             ` Anh Vo
  2 siblings, 1 reply; 34+ messages in thread
From: Bob Duff @ 2016-01-06 14:25 UTC (permalink / raw)


Anh Vo <anhvofrcaus@gmail.com> writes:

> On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
>> On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
>> > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
>> > > Hi Bob,
>> > > 
>> > > Thanks for writing back.  This is the entire example:
>> > > http://pastebin.com/GEJT3WzL
>> >  
>> > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
>> > 
>> >   function Division(
>> >     Input1 : in Integer;
>> >     Input2 : in Integer)
>> >       return Integer
>> >    with pre => Input2 /= 0;

I prefer predicates in a case like that:

    subtype Nonzero is Integer with Predicate => Nonzero /= 0;

And then Input2 can be of subtype Nonzero.  (Predicate is specific to
GNAT; use Static_Predicate if you want to conform to the Ada standard.)

>> I'm not sure that that worked.  I added it to my ads file and after
>> compilation and then re-running the application, this is what I got:
>> 
>> ....
>> 
>>  Division:        4
>> 
>> 
>> raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
>> 
>> Shouldn't the division function been prevented from running the actual division operation beforehand?
>
> The preconditions and postconditions are controlled by pragma
> Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top
> of the package specification. Absent of this pragma is equivalent to pragma
> Assertion_Policy (Ignore). That means these conditions are ignored. By the way,
> ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.

I wouldn't bother fooling about with Assertion_Policy.
Just use the -gnata switch.

If you do use Assertion_Policy, you probably want it in a global
configuration file, so it applies to all of your code.

- Bob

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

* Re: Instantiating package problems
  2016-01-06 14:25           ` Bob Duff
@ 2016-01-06 23:48             ` Anh Vo
  0 siblings, 0 replies; 34+ messages in thread
From: Anh Vo @ 2016-01-06 23:48 UTC (permalink / raw)


On Wednesday, January 6, 2016 at 6:25:47 AM UTC-8, Bob Duff wrote:
> Anh Vo <anhvofrcaus@gmail.com> writes:
> 
> > On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> >> On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> >> > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> >> > > Hi Bob,
> >> > > 
> >> > > Thanks for writing back.  This is the entire example:
> >> > > http://pastebin.com/GEJT3WzL
> >> >  
> >> > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> >> > 
> >> >   function Division(
> >> >     Input1 : in Integer;
> >> >     Input2 : in Integer)
> >> >       return Integer
> >> >    with pre => Input2 /= 0;
> 
> I prefer predicates in a case like that:
> 
>     subtype Nonzero is Integer with Predicate => Nonzero /= 0;
> 
> And then Input2 can be of subtype Nonzero.  (Predicate is specific to
> GNAT; use Static_Predicate if you want to conform to the Ada standard.)
> 
> >> I'm not sure that that worked.  I added it to my ads file and after
> >> compilation and then re-running the application, this is what I got:
> >> 
> >> ....
> >> 
> >>  Division:        4
> >> 
> >> 
> >> raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> >> 
> >> Shouldn't the division function been prevented from running the actual division operation beforehand?
> >
> > The preconditions and postconditions are controlled by pragma
> > Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top
> > of the package specification. Absent of this pragma is equivalent to pragma
> > Assertion_Policy (Ignore). That means these conditions are ignored. By the way,
> > ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.
> 
> I wouldn't bother fooling about with Assertion_Policy.
> Just use the -gnata switch.

I like to stay away from compiler dependence as much as I can. Thus, I chose to stay with Ada Standard in this case.
 
> If you do use Assertion_Policy, you probably want it in a global
> configuration file, so it applies to all of your code.

I agree that this is a good advice for large number of packages.

Anh Vo


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

* Re: Instantiating package problems
  2016-01-06  5:07             ` Anh Vo
@ 2016-01-07  4:41               ` Andrew Shvets
  2016-01-07  5:41                 ` Anh Vo
  0 siblings, 1 reply; 34+ messages in thread
From: Andrew Shvets @ 2016-01-07  4:41 UTC (permalink / raw)


On Wednesday, January 6, 2016 at 12:07:15 AM UTC-5, Anh Vo wrote:
> On Tuesday, January 5, 2016 at 9:00:50 PM UTC-8, Andrew Shvets wrote:
> > On Tuesday, January 5, 2016 at 11:52:00 PM UTC-5, Anh Vo wrote:
> > > On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> > > > On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> > > > > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > > > > > Hi Bob,
> > > > > > 
> > > > > > Thanks for writing back.  This is the entire example:
> > > > > > http://pastebin.com/GEJT3WzL
> > > > >  
> > > > > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> > > > > 
> > > > >   function Division(
> > > > >     Input1 : in Integer;
> > > > >     Input2 : in Integer)
> > > > >       return Integer
> > > > >    with pre => Input2 /= 0;
> > > > > 
> > > > > Anh Vo
> > > > 
> > > > I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:
> > > > 
> > > > ....
> > > > 
> > > >  Division:        4
> > > > 
> > > > 
> > > > raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> > > > 
> > > > Shouldn't the division function been prevented from running the actual division operation beforehand?
> > > 
> > > The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.
> > 
> > This is how the body looks like now:
> > http://pastebin.com/Mt0E0HAD
> > 
> > I'm still getting a constraint error.
> 
> I only saw the pragma placed inside the package body. It should be placed in the package specification.

Alright, I put the pragma before each package keyword (in the body and the declaration) and this is what I got:

$ gnatmake -g main.adb
gcc -c -g main.adb
calculator.ads:5:01: pragma "assertion_policy" is not in declarative part or package spec
gnatmake: "main.adb" compilation error


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

* Re: Instantiating package problems
  2016-01-06 13:07             ` G.B.
@ 2016-01-07  4:42               ` Andrew Shvets
  0 siblings, 0 replies; 34+ messages in thread
From: Andrew Shvets @ 2016-01-07  4:42 UTC (permalink / raw)


On Wednesday, January 6, 2016 at 8:07:45 AM UTC-5, G.B. wrote:
> On 06.01.16 06:00, Andrew Shvets wrote:
> > On Tuesday, January 5, 2016 at 11:52:00 PM UTC-5, Anh Vo wrote:
> 
> >> The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.
> >
> > This is how the body looks like now:
> > http://pastebin.com/Mt0E0HAD
> >
> > I'm still getting a constraint error.
> >
> 
> You should see something like this, after adding Assertion_Policy
> in the way Anh Vo has described:
> 
> raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from 
> shvets.ada:15
> 
> If you know that what Dmitry has explained is true,
> you could state it as a workable approximation,
> so that clients of the package know what to do when
> the programmers are not certain about all implications,
> practical and theoretical, of predefined division "/"
> in Input1/Input2, Integer'[Base']Range, and more:
> 
> 
>     Extra_Value : constant Boolean :=
>       not (Integer'Last = -Integer'First);
> 
>     function Division
>       (Input1 : in Integer;
>        Input2 : in Integer)
>       return Integer
>     with
>       Pre =>
>         Input2 /= 0
>         and
>         (if Extra_Value
>          then not (Input1 = Integer'First and Input2 = -1)),
>       Post =>
>         Input1/Input2 in Integer'Range
>         and
>         Division'Result = Input1/Input2;

It makes sense in principle.  I've seen something similar in erlang where you could check if one of the inputs is an integer, float, etc.

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

* Re: Instantiating package problems
  2016-01-07  4:41               ` Andrew Shvets
@ 2016-01-07  5:41                 ` Anh Vo
  2016-01-09 20:14                   ` Andrew Shvets
  0 siblings, 1 reply; 34+ messages in thread
From: Anh Vo @ 2016-01-07  5:41 UTC (permalink / raw)


On Wednesday, January 6, 2016 at 8:41:38 PM UTC-8, Andrew Shvets wrote:
> On Wednesday, January 6, 2016 at 12:07:15 AM UTC-5, Anh Vo wrote:
> > On Tuesday, January 5, 2016 at 9:00:50 PM UTC-8, Andrew Shvets wrote:
> > > On Tuesday, January 5, 2016 at 11:52:00 PM UTC-5, Anh Vo wrote:
> > > > On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> > > > > On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> > > > > > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > > > > > > Hi Bob,
> > > > > > > 
> > > > > > > Thanks for writing back.  This is the entire example:
> > > > > > > http://pastebin.com/GEJT3WzL
> > > > > >  
> > > > > > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> > > > > > 
> > > > > >   function Division(
> > > > > >     Input1 : in Integer;
> > > > > >     Input2 : in Integer)
> > > > > >       return Integer
> > > > > >    with pre => Input2 /= 0;
> > > > > > 
> > > > > > Anh Vo
> > > > > 
> > > > > I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:
> > > > > 
> > > > > ....
> > > > > 
> > > > >  Division:        4
> > > > > 
> > > > > 
> > > > > raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> > > > > 
> > > > > Shouldn't the division function been prevented from running the actual division operation beforehand?
> > > > 
> > > > The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.
> > > 
> > > This is how the body looks like now:
> > > http://pastebin.com/Mt0E0HAD
> > > 
> > > I'm still getting a constraint error.
> > 
> > I only saw the pragma placed inside the package body. It should be placed in the package specification.
> 
> Alright, I put the pragma before each package keyword (in the body and the declaration) and this is what I got:
> 
> $ gnatmake -g main.adb
> gcc -c -g main.adb
> calculator.ads:5:01: pragma "assertion_policy" is not in declarative part or package spec
> gnatmake: "main.adb" compilation error

what I meant was on top of the package specification as shown below.

pragma Assertion_Policy (Check);
with Ada.Text_IO;

package Calculator is
--...
end Calculator;

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

* Re: Instantiating package problems
  2016-01-07  5:41                 ` Anh Vo
@ 2016-01-09 20:14                   ` Andrew Shvets
  2016-01-10 19:43                     ` Andrew Shvets
  0 siblings, 1 reply; 34+ messages in thread
From: Andrew Shvets @ 2016-01-09 20:14 UTC (permalink / raw)


On Thursday, January 7, 2016 at 12:41:33 AM UTC-5, Anh Vo wrote:
> On Wednesday, January 6, 2016 at 8:41:38 PM UTC-8, Andrew Shvets wrote:
> > On Wednesday, January 6, 2016 at 12:07:15 AM UTC-5, Anh Vo wrote:
> > > On Tuesday, January 5, 2016 at 9:00:50 PM UTC-8, Andrew Shvets wrote:
> > > > On Tuesday, January 5, 2016 at 11:52:00 PM UTC-5, Anh Vo wrote:
> > > > > On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> > > > > > On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> > > > > > > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > > > > > > > Hi Bob,
> > > > > > > > 
> > > > > > > > Thanks for writing back.  This is the entire example:
> > > > > > > > http://pastebin.com/GEJT3WzL
> > > > > > >  
> > > > > > > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> > > > > > > 
> > > > > > >   function Division(
> > > > > > >     Input1 : in Integer;
> > > > > > >     Input2 : in Integer)
> > > > > > >       return Integer
> > > > > > >    with pre => Input2 /= 0;
> > > > > > > 
> > > > > > > Anh Vo
> > > > > > 
> > > > > > I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:
> > > > > > 
> > > > > > ....
> > > > > > 
> > > > > >  Division:        4
> > > > > > 
> > > > > > 
> > > > > > raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> > > > > > 
> > > > > > Shouldn't the division function been prevented from running the actual division operation beforehand?
> > > > > 
> > > > > The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.
> > > > 
> > > > This is how the body looks like now:
> > > > http://pastebin.com/Mt0E0HAD
> > > > 
> > > > I'm still getting a constraint error.
> > > 
> > > I only saw the pragma placed inside the package body. It should be placed in the package specification.
> > 
> > Alright, I put the pragma before each package keyword (in the body and the declaration) and this is what I got:
> > 
> > $ gnatmake -g main.adb
> > gcc -c -g main.adb
> > calculator.ads:5:01: pragma "assertion_policy" is not in declarative part or package spec
> > gnatmake: "main.adb" compilation error
> 
> what I meant was on top of the package specification as shown below.
> 
> pragma Assertion_Policy (Check);
> with Ada.Text_IO;
> 
> package Calculator is
> --...
> end Calculator;

Got, thanks, it works now.

And NOW I better understand how the constructor and destructor works in the Ada language.  Before, I was coming from a C++ perspective and looking at it while nothing was making any sense.

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

* Re: Instantiating package problems
  2016-01-09 20:14                   ` Andrew Shvets
@ 2016-01-10 19:43                     ` Andrew Shvets
  2016-01-10 21:38                       ` Jeffrey R. Carter
  2016-01-10 21:50                       ` Georg Bauhaus
  0 siblings, 2 replies; 34+ messages in thread
From: Andrew Shvets @ 2016-01-10 19:43 UTC (permalink / raw)


On Saturday, January 9, 2016 at 3:14:19 PM UTC-5, Andrew Shvets wrote:
> On Thursday, January 7, 2016 at 12:41:33 AM UTC-5, Anh Vo wrote:
> > On Wednesday, January 6, 2016 at 8:41:38 PM UTC-8, Andrew Shvets wrote:
> > > On Wednesday, January 6, 2016 at 12:07:15 AM UTC-5, Anh Vo wrote:
> > > > On Tuesday, January 5, 2016 at 9:00:50 PM UTC-8, Andrew Shvets wrote:
> > > > > On Tuesday, January 5, 2016 at 11:52:00 PM UTC-5, Anh Vo wrote:
> > > > > > On Tuesday, January 5, 2016 at 7:31:00 PM UTC-8, Andrew Shvets wrote:
> > > > > > > On Monday, January 4, 2016 at 3:49:32 PM UTC-5, Anh Vo wrote:
> > > > > > > > On Sunday, January 3, 2016 at 4:07:30 PM UTC-8, Andrew Shvets wrote:
> > > > > > > > > Hi Bob,
> > > > > > > > > 
> > > > > > > > > Thanks for writing back.  This is the entire example:
> > > > > > > > > http://pastebin.com/GEJT3WzL
> > > > > > > >  
> > > > > > > > Just recommend to add a precondition to function Division as shown below. By the way, this feature is part of latest Ada (Ada 2012). In addition, you should think about adding precondition to other operations such as Addition where Input1 + Input2 <= Integer'Last and Input1 + Input2 >= Integer'Last. 
> > > > > > > > 
> > > > > > > >   function Division(
> > > > > > > >     Input1 : in Integer;
> > > > > > > >     Input2 : in Integer)
> > > > > > > >       return Integer
> > > > > > > >    with pre => Input2 /= 0;
> > > > > > > > 
> > > > > > > > Anh Vo
> > > > > > > 
> > > > > > > I'm not sure that that worked.  I added it to my ads file and after compilation and then re-running the application, this is what I got:
> > > > > > > 
> > > > > > > ....
> > > > > > > 
> > > > > > >  Division:        4
> > > > > > > 
> > > > > > > 
> > > > > > > raised CONSTRAINT_ERROR : calculator.adb:33 divide by zero
> > > > > > > 
> > > > > > > Shouldn't the division function been prevented from running the actual division operation beforehand?
> > > > > > 
> > > > > > The preconditions and postconditions are controlled by pragma Assertion_Policy. Thus, pragma Assertion_Policy(Check) must be added at the top of the package specification. Absent of this pragma is equivalent to pragma Assertion_Policy (Ignore). That means these conditions are ignored. By the way, ASSERTION_ERROR exception would be raised instead of CONSTRAINT_ERROR.
> > > > > 
> > > > > This is how the body looks like now:
> > > > > http://pastebin.com/Mt0E0HAD
> > > > > 
> > > > > I'm still getting a constraint error.
> > > > 
> > > > I only saw the pragma placed inside the package body. It should be placed in the package specification.
> > > 
> > > Alright, I put the pragma before each package keyword (in the body and the declaration) and this is what I got:
> > > 
> > > $ gnatmake -g main.adb
> > > gcc -c -g main.adb
> > > calculator.ads:5:01: pragma "assertion_policy" is not in declarative part or package spec
> > > gnatmake: "main.adb" compilation error
> > 
> > what I meant was on top of the package specification as shown below.
> > 
> > pragma Assertion_Policy (Check);
> > with Ada.Text_IO;
> > 
> > package Calculator is
> > --...
> > end Calculator;
> 
> Got, thanks, it works now.
> 
> And NOW I better understand how the constructor and destructor works in the Ada language.  Before, I was coming from a C++ perspective and looking at it while nothing was making any sense.

Potentially stupid question.  When you instantiate a record (which is described in the private portion of a package), does that mean that the insides (the different types, lists, arrays, etc.) that compose it are not visible to others except through setter and getter methods?

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

* Re: Instantiating package problems
  2016-01-10 19:43                     ` Andrew Shvets
@ 2016-01-10 21:38                       ` Jeffrey R. Carter
  2016-01-10 21:50                       ` Georg Bauhaus
  1 sibling, 0 replies; 34+ messages in thread
From: Jeffrey R. Carter @ 2016-01-10 21:38 UTC (permalink / raw)


On 01/10/2016 12:43 PM, Andrew Shvets wrote:
> Potentially stupid question.  When you instantiate a record (which is
> described in the private portion of a package), does that mean that the
> insides (the different types, lists, arrays, etc.) that compose it are not
> visible to others except through setter and getter methods?

Is there some reason you have to quote the entirety of 9 msgs to ask this question?

The client of a pkg with a private type does not have visibility of the full
type declaration in the private part. The only things a client can do with a
private type is declare objects of the type and call subprograms operating on
the type. (If the type is not declared limited, the client can also assign
values and call "=" and "/=".)

"Instantiate" is an Ada technical term with a specific meaning relating to
generics. It is meaningless applied to a record type. The Ada technical term is
"declare an object of a record type", often shortened to "declare a record".

-- 
Jeff Carter
"Death awaits you all, with nasty, big, pointy teeth!"
Monty Python & the Holy Grail
20

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

* Re: Instantiating package problems
  2016-01-10 19:43                     ` Andrew Shvets
  2016-01-10 21:38                       ` Jeffrey R. Carter
@ 2016-01-10 21:50                       ` Georg Bauhaus
  2016-01-10 21:58                         ` Andrew Shvets
  1 sibling, 1 reply; 34+ messages in thread
From: Georg Bauhaus @ 2016-01-10 21:50 UTC (permalink / raw)


On 10.01.16 20:43, Andrew Shvets wrote:
>
>   When you instantiate a record (which is described in the private portion of a package), does that mean that the insides (the different types, lists, arrays, etc.) that compose it are not visible to others except through setter and getter methods?
>

when a type is declared as a private type in some page P,

package P is

    type T ... is ... private;

then, outside the package, only public operations are visible,
basically anything that follows the declaration until another
"private" introduces the private part of P. Hence, no data
components of any object of type P.T declared outside.

Suppose

package P is
    type T is private;
    procedure op1 (Object : in out T);
private
   type T is record
      c1 : T1 := Foo(N);
      c2 : T2;
   end record;
end P;

then I think it is fair to say this C++ type is an analogue,
perhaps declared in a file "p.hpp", or in namespace P:

struct T {
private:
   T1 c1;
   T2 c2;
public:
   T() : c1(foo(n))
    {
   }
   void op1(void);
};



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

* Re: Instantiating package problems
  2016-01-10 21:50                       ` Georg Bauhaus
@ 2016-01-10 21:58                         ` Andrew Shvets
  0 siblings, 0 replies; 34+ messages in thread
From: Andrew Shvets @ 2016-01-10 21:58 UTC (permalink / raw)


On Sunday, January 10, 2016 at 4:50:15 PM UTC-5, Georg Bauhaus wrote:
> On 10.01.16 20:43, Andrew Shvets wrote:
> >
> >   When you instantiate a record (which is described in the private portion of a package), does that mean that the insides (the different types, lists, arrays, etc.) that compose it are not visible to others except through setter and getter methods?
> >
> 
> when a type is declared as a private type in some page P,
> 
> package P is
> 
>     type T ... is ... private;
> 
> then, outside the package, only public operations are visible,
> basically anything that follows the declaration until another
> "private" introduces the private part of P. Hence, no data
> components of any object of type P.T declared outside.
> 
> Suppose
> 
> package P is
>     type T is private;
>     procedure op1 (Object : in out T);
> private
>    type T is record
>       c1 : T1 := Foo(N);
>       c2 : T2;
>    end record;
> end P;
> 
> then I think it is fair to say this C++ type is an analogue,
> perhaps declared in a file "p.hpp", or in namespace P:
> 
> struct T {
> private:
>    T1 c1;
>    T2 c2;
> public:
>    T() : c1(foo(n))
>     {
>    }
>    void op1(void);
> };

Thanks for your reply.  I understand now.

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

end of thread, other threads:[~2016-01-10 21:58 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-03 18:40 Instantiating package problems Andrew Shvets
2016-01-03 20:27 ` Georg Bauhaus
2016-01-03 21:21   ` Andrew Shvets
2016-01-03 21:04 ` Jeffrey R. Carter
2016-01-03 21:27   ` Andrew Shvets
2016-01-03 22:39     ` Jeffrey R. Carter
2016-01-03 22:08 ` Bob Duff
2016-01-04  0:07   ` Andrew Shvets
2016-01-04  0:30     ` Andrew Shvets
2016-01-04 13:43       ` G.B.
2016-01-04 14:23       ` Brian Drummond
2016-01-04 20:49     ` Anh Vo
2016-01-04 21:10       ` Dmitry A. Kazakov
2016-01-04 22:39         ` Anh Vo
2016-01-05  1:42           ` Anh Vo
2016-01-05  7:35           ` Dmitry A. Kazakov
2016-01-06  2:46       ` Andrew Shvets
2016-01-06  8:53         ` Dmitry A. Kazakov
2016-01-06  3:30       ` Andrew Shvets
2016-01-06  4:51         ` Anh Vo
2016-01-06  4:54           ` Anh Vo
2016-01-06  5:00           ` Andrew Shvets
2016-01-06  5:07             ` Anh Vo
2016-01-07  4:41               ` Andrew Shvets
2016-01-07  5:41                 ` Anh Vo
2016-01-09 20:14                   ` Andrew Shvets
2016-01-10 19:43                     ` Andrew Shvets
2016-01-10 21:38                       ` Jeffrey R. Carter
2016-01-10 21:50                       ` Georg Bauhaus
2016-01-10 21:58                         ` Andrew Shvets
2016-01-06 13:07             ` G.B.
2016-01-07  4:42               ` Andrew Shvets
2016-01-06 14:25           ` Bob Duff
2016-01-06 23:48             ` Anh Vo

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