comp.lang.ada
 help / color / mirror / Atom feed
* worrying behaviour
@ 2008-05-02 15:26 echancrure
  2008-05-02 15:54 ` Adam Beneschan
  0 siblings, 1 reply; 6+ messages in thread
From: echancrure @ 2008-05-02 15:26 UTC (permalink / raw)


After the discussion on static expressions etc.

I came up against this problem which I thought was initially related
to it but probably not.

let's say I have:

with Ada.Text_IO;  use Ada.Text_IO;
with ints;
procedure static is
   function "-"(L, R : ints.My_Int) return ints.My_int renames
ints."-";
   function "-"(L : ints.My_Int) return ints.My_int renames ints."-";
   Y : constant ints.My_int := -1;
   Z : constant ints.My_int := 1-1;
begin
   Put_Line (ints.My_Int'Image (Y) & ints.My_Int'Image (Z));
end static;

and

package ints
is
  type My_Int is range -100..100;
  function "-"   (L, R : My_Int) return My_int;
end ints;

package body ints
is
  function "-" (L, R : My_Int) return My_Int
  is
  begin
    return 42;
  end "-";
end ints;

So basically, I have forgotten to define unary "-" in the the ints
package.

gnat does not complain and the .exe returns '-1 42' as would be
expected without the unary - rename.

Here however I have renamed the unary - to something that does not
exist.

Surely an error should be generated here. Otherwise this is very
dangerous behaviour.

Please enlight me.



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

* Re: worrying behaviour
  2008-05-02 15:26 worrying behaviour echancrure
@ 2008-05-02 15:54 ` Adam Beneschan
  2008-05-02 17:41   ` echancrure
  2008-05-03  1:15   ` Randy Brukardt
  0 siblings, 2 replies; 6+ messages in thread
From: Adam Beneschan @ 2008-05-02 15:54 UTC (permalink / raw)


On May 2, 8:26 am, echancr...@gmail.com wrote:
> After the discussion on static expressions etc.
>
> I came up against this problem which I thought was initially related
> to it but probably not.
>
> let's say I have:
>
> with Ada.Text_IO;  use Ada.Text_IO;
> with ints;
> procedure static is
>    function "-"(L, R : ints.My_Int) return ints.My_int renames
> ints."-";
>    function "-"(L : ints.My_Int) return ints.My_int renames ints."-";
>    Y : constant ints.My_int := -1;
>    Z : constant ints.My_int := 1-1;
> begin
>    Put_Line (ints.My_Int'Image (Y) & ints.My_Int'Image (Z));
> end static;
>
> and
>
> package ints
> is
>   type My_Int is range -100..100;
>   function "-"   (L, R : My_Int) return My_int;
> end ints;
>
> package body ints
> is
>   function "-" (L, R : My_Int) return My_Int
>   is
>   begin
>     return 42;
>   end "-";
> end ints;
>
> So basically, I have forgotten to define unary "-" in the the ints
> package.

It's automatically defined for all integer types (such as My_Int), as
are unary "+" and binary "+", "-", "*", "/", etc.  In the Ints
package, you've overridden the binary "-",  but the other predefined
operations are not affected and are still visible.  So unary "-" does
exist.

I'm not sure that there's a good solution in Ada.  If you really
wanted to make sure that the only operators available for My_Int are
the ones that you remembered to override, you could declare My_Int
private, but then you'd lose the ability to have numeric literals for
that type (in other packages).  I suppose that having some sort of
language construct that says "kill all predefined operators for a
type" would be useful in your case.

On the other hand, your example is obviously not a real-world case,
and I'm having trouble envisioning a case where this would be an
issue.  In a real-life situation, either it would be OK to make the
type a private type, or (if the type really were an integer type)
there wouldn't be any problem with allowing the predefined operators
to exist.  (Especially unary "-".  I know that "*" and "/" can cause
headaches for types that represent measurements, but addition and
comparison operations don't have this issue.)  Perhaps someone could
give an example of a situation where a feature that prevents
predefined integer operations from being defined would be useful, but
I can't think of one offhand.

Are you working on a real-life project where this is a real danger, or
are you simply trying to test your understanding of the language?


> gnat does not complain and the .exe returns '-1 42' as would be
> expected without the unary - rename.
>
> Here however I have renamed the unary - to something that does not
> exist.

It does exist, as I've explained.


> Surely an error should be generated here. Otherwise this is very
> dangerous behaviour.

There are cases where compilers sometimes generate warnings, because
while they are legal Ada there is a very high probability that the
programmer did something wrong.  An example would be defining a "+"
function that renames a "*" defined in another package.

However, defining a unary "-" that renames another unary "-" is a
common idiom (and was even moreso before USE TYPE was added to Ada
95).  I don't see anything in this code that a compiler could
reasonably warn about, although perhaps others may have different
opinions about that.

                                 -- Adam




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

* Re: worrying behaviour
  2008-05-02 15:54 ` Adam Beneschan
@ 2008-05-02 17:41   ` echancrure
  2008-05-02 18:31     ` Adam Beneschan
  2008-05-03  1:15   ` Randy Brukardt
  1 sibling, 1 reply; 6+ messages in thread
From: echancrure @ 2008-05-02 17:41 UTC (permalink / raw)


On May 2, 4:54 pm, Adam Beneschan <a...@irvine.com> wrote:
> On May 2, 8:26 am, echancr...@gmail.com wrote:
>
>
>
> > After the discussion on static expressions etc.
>
> > I came up against this problem which I thought was initially related
> > to it but probably not.
>
> > let's say I have:
>
> > with Ada.Text_IO;  use Ada.Text_IO;
> > with ints;
> > procedure static is
> >    function "-"(L, R : ints.My_Int) return ints.My_int renames
> > ints."-";
> >    function "-"(L : ints.My_Int) return ints.My_int renames ints."-";
> >    Y : constant ints.My_int := -1;
> >    Z : constant ints.My_int := 1-1;
> > begin
> >    Put_Line (ints.My_Int'Image (Y) & ints.My_Int'Image (Z));
> > end static;
>
> > and
>
> > package ints
> > is
> >   type My_Int is range -100..100;
> >   function "-"   (L, R : My_Int) return My_int;
> > end ints;
>
> > package body ints
> > is
> >   function "-" (L, R : My_Int) return My_Int
> >   is
> >   begin
> >     return 42;
> >   end "-";
> > end ints;
>
> > So basically, I have forgotten to define unary "-" in the the ints
> > package.
>
> It's automatically defined for all integer types (such as My_Int), as
> are unary "+" and binary "+", "-", "*", "/", etc.  In the Ints
> package, you've overridden the binary "-",  but the other predefined
> operations are not affected and are still visible.  So unary "-" does
> exist.
>
> I'm not sure that there's a good solution in Ada.  If you really
> wanted to make sure that the only operators available for My_Int are
> the ones that you remembered to override, you could declare My_Int
> private, but then you'd lose the ability to have numeric literals for
> that type (in other packages).  I suppose that having some sort of
> language construct that says "kill all predefined operators for a
> type" would be useful in your case.
>
> On the other hand, your example is obviously not a real-world case,
> and I'm having trouble envisioning a case where this would be an
> issue.  In a real-life situation, either it would be OK to make the
> type a private type, or (if the type really were an integer type)
> there wouldn't be any problem with allowing the predefined operators
> to exist.  (Especially unary "-".  I know that "*" and "/" can cause
> headaches for types that represent measurements, but addition and
> comparison operations don't have this issue.)  Perhaps someone could
> give an example of a situation where a feature that prevents
> predefined integer operations from being defined would be useful, but
> I can't think of one offhand.
>
> Are you working on a real-life project where this is a real danger, or
> are you simply trying to test your understanding of the language?
>
> > gnat does not complain and the .exe returns '-1 42' as would be
> > expected without the unary - rename.
>
> > Here however I have renamed the unary - to something that does not
> > exist.
>
> It does exist, as I've explained.
>
> > Surely an error should be generated here. Otherwise this is very
> > dangerous behaviour.
>
> There are cases where compilers sometimes generate warnings, because
> while they are legal Ada there is a very high probability that the
> programmer did something wrong.  An example would be defining a "+"
> function that renames a "*" defined in another package.
>
> However, defining a unary "-" that renames another unary "-" is a
> common idiom (and was even moreso before USE TYPE was added to Ada
> 95).  I don't see anything in this code that a compiler could
> reasonably warn about, although perhaps others may have different
> opinions about that.
>
>                                  -- Adam

Thanks Adam for your comprehensive answer.
I know there is no error here, I just thought that if you explicitly
bother to provide a renaming operator declaration it would be
reasonable for the compiler to expect an explicit definition for it...

Of course declaring the type private would highlight the problem
but ... are you really sure that in the real world those mistakes are
not made? (would be pretty hard to detect and would probably only be
revealed on boundary cases)

After all what is the point of renaming an operator and not provide an
actual body for it but the default one?
Does it not deserve a warning? Is this allowed in Spark (I think it is
but I have no Spark checker)?

regards,
chris





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

* Re: worrying behaviour
  2008-05-02 17:41   ` echancrure
@ 2008-05-02 18:31     ` Adam Beneschan
  0 siblings, 0 replies; 6+ messages in thread
From: Adam Beneschan @ 2008-05-02 18:31 UTC (permalink / raw)


On May 2, 10:41 am, echancr...@gmail.com wrote:

> Thanks Adam for your comprehensive answer.
> I know there is no error here, I just thought that if you explicitly
> bother to provide a renaming operator declaration it would be
> reasonable for the compiler to expect an explicit definition for it...

Not at all; I think it's quite common to rename implicitly declared
operators.


> Of course declaring the type private would highlight the problem
> but ... are you really sure that in the real world those mistakes are
> not made? (would be pretty hard to detect and would probably only be
> revealed on boundary cases)

They may well be made.  But a compiler can't reasonably catch all
mistakes.


> After all what is the point of renaming an operator and not provide an
> actual body for it but the default one?

To be able to use the operator without having to USE the package.  USE
TYPE makes this less necessary, but there's a lot of legacy code out
there written before Ada 95.  Also, there may be reasons why USE TYPE
is undesirable in particular situations, but I'm not sure what they
are... perhaps others could elaborate if there are.

Actually, now that I think of it, your question doesn't make that much
sense.  Other than the reason I've alluded to (i.e. making an operator
visible), I don't see any point to renaming an operator that *does*
have an actual body for it---I don't see why the explicitness or
implicitness of the operator's definition makes any difference.

(There are cases where you need a rename to avoid an ambiguity, but in
those cases you wouldn't be renaming an operator to the same operator
string, so I'm assuming that case isn't relevant to this discussion.)

                             -- Adam




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

* Re: worrying behaviour
  2008-05-02 15:54 ` Adam Beneschan
  2008-05-02 17:41   ` echancrure
@ 2008-05-03  1:15   ` Randy Brukardt
  2008-05-03  2:04     ` Adam Beneschan
  1 sibling, 1 reply; 6+ messages in thread
From: Randy Brukardt @ 2008-05-03  1:15 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message
news:ea92a206-7617-4968-90c2-31fcc30d5e40@r9g2000prd.googlegroups.com...
...
> I'm not sure that there's a good solution in Ada.  If you really
> wanted to make sure that the only operators available for My_Int are
> the ones that you remembered to override, you could declare My_Int
> private, but then you'd lose the ability to have numeric literals for
> that type (in other packages).  I suppose that having some sort of
> language construct that says "kill all predefined operators for a
> type" would be useful in your case.

That's not available, but you can kill them one-by-one by declaring them
abstract:

   function "-" (R : My_Int) return My_int is abstract;

makes "-" effectively undefined for type My_Int. (This is new in Ada 2005,
in Ada 95 it is defined and uncallable -- the difference is that it might
conflict with some user-defined routine and cause trouble.)

                      Randy.





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

* Re: worrying behaviour
  2008-05-03  1:15   ` Randy Brukardt
@ 2008-05-03  2:04     ` Adam Beneschan
  0 siblings, 0 replies; 6+ messages in thread
From: Adam Beneschan @ 2008-05-03  2:04 UTC (permalink / raw)


On May 2, 6:15 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> "Adam Beneschan" <a...@irvine.com> wrote in message
>
> news:ea92a206-7617-4968-90c2-31fcc30d5e40@r9g2000prd.googlegroups.com...
> ...
>
> > I'm not sure that there's a good solution in Ada.  If you really
> > wanted to make sure that the only operators available for My_Int are
> > the ones that you remembered to override, you could declare My_Int
> > private, but then you'd lose the ability to have numeric literals for
> > that type (in other packages).  I suppose that having some sort of
> > language construct that says "kill all predefined operators for a
> > type" would be useful in your case.
>
> That's not available, but you can kill them one-by-one by declaring them
> abstract:
>
>    function "-" (R : My_Int) return My_int is abstract;
>
> makes "-" effectively undefined for type My_Int. (This is new in Ada 2005,
> in Ada 95 it is defined and uncallable -- the difference is that it might
> conflict with some user-defined routine and cause trouble.)

Right.  The reason I didn't mention this was because the original
problem appeared to be caused (perhaps hypothetically) by someone
forgetting to override an operator in the package; and if they forgot
to override it they wouldn't remember to override it with an abstract
function either.  That's why one construct to get rid of all the
predefined functions would work better here, although I'm still not
convinced that there's a real need for it.

                              -- Adam



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

end of thread, other threads:[~2008-05-03  2:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-05-02 15:26 worrying behaviour echancrure
2008-05-02 15:54 ` Adam Beneschan
2008-05-02 17:41   ` echancrure
2008-05-02 18:31     ` Adam Beneschan
2008-05-03  1:15   ` Randy Brukardt
2008-05-03  2:04     ` Adam Beneschan

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