TEAM-ADA Archives

Team Ada: Ada Programming Language Advocacy


Options: Use Forum View

Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
"Dr. Alan Barnes" <[log in to unmask]>
Reply To:
Dr. Alan Barnes
Wed, 21 Apr 1999 11:57:20 +0100
text/plain (103 lines)
I couldn't see why you want to have Max and Min as binary
operators as the attribute functions (Integer'Max etc.) seem adequate.

But if you do, it would be better to overload other operators
which don't normally have a meaning for numbers (eg "&").

I think the answers to your two questions are:

> 1. Is it possible to generate user defined binary operators (in
>    Ada)?

No, you can only overload existing operators.

> 2. If not, then why not?

I guess one reason for this is practical: it would require fundamental
changes to the parsing routines in the compiler if completely new
operator symbols with extra precedence levels were introduced in the

A related issue arose a few weeks ago when I redefined "/" and "**"
for modular numbers in a package of the form:

   TYPE Zed_N IS MOD <>;

   NotInvertible, Zero_To_Power_Zero, Modulus_Too_Large : EXCEPTION;

   FUNCTION "**"(A : Zed_N; N : Integer) RETURN Zed_N;
   -- returns A**N. When N < 0 and Inverse(A) does not exist
   -- raises the exception NotInvertible
   -- raises the exception Zero_To_Power_Zero if 0**0 is formed.

   FUNCTION "/"(A, B : Zed_N) RETURN Zed_N;
   -- returns A*Inverse(B) mod n if Inverse(B) exists
   -- else raises the exception NotInvertible

   FUNCTION Inverse(A : Zed_N) RETURN Zed_N;
   -- returns the inverse of A mod n if it exists
   -- else raises the exception NotInvertible

   FUNCTION IsInvertible(A : Zed_N) RETURN Boolean;
   -- returns True if A has an inverse mod n, otherwise returns False

END Mod_Pack;

If simply instantiate the package  and USE it in a client

   TYPE Z31 IS MOD 31;
   PACKAGE Mod31 IS NEW Mod_Pack(Z31);
   USE Mod31;

then the definitions of Standard."/" and Standard."**" are not overridden and
a program using "/" and "**" with arguments of type Z31 is ambiguous
and will not compile (with gnat).

Suprisingly the situation is different if the package is not generic:

   TYPE Z31 IS MOD 31;
   -- rest of package  unchanged (apart from renaming fo Zed_N)

If you simply WITH and USE this package  the program compiles but the
new overloadings of "/" and "**" are ignored and the ones from
Standard are used.

To override the Standard definitions in the client in either case you
can do

   FUNCTION "/"(A, B : Z31) RETURN Z31 RENAMES Mod31."/";
   FUNCTION "**"(A : Z31; N : Integer) RETURN Z31 RENAMES Mod31."**";

This seems rather messy, but I couldn't see a way of avoiding it.

I guess the reason for the above is that you cannnot TACITLY change the
meaning of a program with a USE which overrides operators in
Standard. However it is not clear to me why the sitaution is different
for generic and non-generic packages.

Also if an operator from Standard is given a new overloading by a
renaming declaration in a (non-generic) package declaration, then a
client program which WITH's and USE's the package and attempts to use
the overloaded operators is again  ambiguous and  will not compile.

Again the reason for the different behaviour is not clear to me.  Is
this situation covered by the LRM?  If so, where?  Or is it a
'feature' in gnat?

   Alan Barnes
   Department of Computer Science and Applied Mathematics
   Aston University
   Aston Triangle
   Birmingham B4 7ET
   U. K.

   Telephone: +44 121 359 3611 Ext. 4663
   E-Mail:  [log in to unmask]  (JANET)
   Fax:     +44 121 333 6215