comp.lang.ada
 help / color / mirror / Atom feed
* Negative float problem
@ 2005-10-26 18:32 Luke
  2005-10-26 19:05 ` Samuel Tardieu
  2005-10-26 20:42 ` Robert A Duff
  0 siblings, 2 replies; 47+ messages in thread
From: Luke @ 2005-10-26 18:32 UTC (permalink / raw)


Hi

If I have two files:
file1:
package file1 is

	type My_Float is digits 6;

end file1;

and file2:
with file1;

procedure file2 is
	X : file1.My_Float := -1.0;
begin
	X := 1.0;
end file2;

and do gnatmake file2.adb i get the following error:
file2.adb:4:31: operator for type "My_Float" defined at file1.ads:3 is
not directly visible
file2.adb:4:31: use clause would make operation legal

There are two solutions:
1) add a use type as sugested
2) Change line 4 to: X : file1.My_Float := file1.My_Float(-1.0);

If 2 works then why doesnt the original?  The same is true for +1.0.
Is this a fault with gcc?

gcc -v gives:
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--host=i386-redhat-linux
Thread model: posix
gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)




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

* Re: Negative float problem
  2005-10-26 18:32 Negative float problem Luke
@ 2005-10-26 19:05 ` Samuel Tardieu
  2005-10-26 20:42 ` Robert A Duff
  1 sibling, 0 replies; 47+ messages in thread
From: Samuel Tardieu @ 2005-10-26 19:05 UTC (permalink / raw)


>>>>> "Luke" == Luke  <lukeedw@hotmail.com> writes:

Luke> If 2 works then why doesnt the original?  The same is true for
Luke> +1.0.  Is this a fault with gcc?

No.

In your first attempt

  X : file1.My_Float := -1.0;

you are trying to use the "-" operator on the My_Float type. The
operator is not immediately visible as it is defined in the file1
package.

In the second attempt

  X : file1.My_Float := file1.My_Float (-1.0);

you are in fact converting the Universal_Float value "-1.0" (which is
obtained after having applied the unary "-" operator on the
Universal_Float value "1.0", and this operator is always visible) to
type My_Float.

In fact, it is equivalent to writing

  Y : constant := -1.0;
  X : file1.My_Float := Y;

If you look at Ada95 grammar (in Annex P if I remember correctly), you
will see that numbers are defined *without* any leading "+" and "-"
signs. Each time you write "-xxx", you apply the unary "-" operator to
"xxx".

Note that you could have written also

  X : file1.My_Float := file1."-" (1.0);

I think that almost any Ada-er has learnt this rule the hard way one
day or another :)

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/sam



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

* Re: Negative float problem
  2005-10-26 18:32 Negative float problem Luke
  2005-10-26 19:05 ` Samuel Tardieu
@ 2005-10-26 20:42 ` Robert A Duff
  2005-10-27  8:05   ` Robert I. Eachus
  1 sibling, 1 reply; 47+ messages in thread
From: Robert A Duff @ 2005-10-26 20:42 UTC (permalink / raw)


"Luke" <lukeedw@hotmail.com> writes:

> Hi
> 
> If I have two files:
> file1:
> package file1 is
> 
> 	type My_Float is digits 6;
> 
> end file1;
> 
> and file2:
> with file1;
> 
> procedure file2 is
> 	X : file1.My_Float := -1.0;
> begin
> 	X := 1.0;
> end file2;
> 
> and do gnatmake file2.adb i get the following error:
> file2.adb:4:31: operator for type "My_Float" defined at file1.ads:3 is
> not directly visible
> file2.adb:4:31: use clause would make operation legal
> 
> There are two solutions:
> 1) add a use type as sugested
> 2) Change line 4 to: X : file1.My_Float := file1.My_Float(-1.0);
> 
> If 2 works then why doesnt the original?  The same is true for +1.0.
> Is this a fault with gcc?

No.  It's a fault with the Ada language.  ;-)
GNAT is implementing the language correctly, here.

Sam Tardieu explained why the second one works, but not the original.

But I suggest using the first solution.  Really, the "use type"
semantics ought to be turned on by default -- you shouldn't have to say
anything special to use the "-" operator.  After all, you don't have
to say anything special to use "1.0" or ":=" on this type!

- Bob



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

* Re: Negative float problem
  2005-10-26 20:42 ` Robert A Duff
@ 2005-10-27  8:05   ` Robert I. Eachus
  2005-10-27 14:48     ` Robert A Duff
  0 siblings, 1 reply; 47+ messages in thread
From: Robert I. Eachus @ 2005-10-27  8:05 UTC (permalink / raw)


Robert A Duff wrote:

> But I suggest using the first solution.  Really, the "use type"
> semantics ought to be turned on by default -- you shouldn't have to say
> anything special to use the "-" operator.  After all, you don't have
> to say anything special to use "1.0" or ":=" on this type!

There was an Ada83 AI on this, usually referred to as the "for I in 
1..-10" problem.  (Yes the loop would be executed zero times, but the 
problem is that an Ada 83 compiler was required to reject the for 
statement.)  Tucker came up with some preference rules that handle some 
of the cases, but the case mentioned here is one of the more refractory 
ones.  It could be solved by having a negation symbol that could be part 
of a numeric literal.  But as long as users are allowed to overload 
operator symbols, the visibility rules will have some edge cases like 
this one.

For example

package file1 is

	type My_Float is digits 6;
         function "-"(L: My_Float) return My_Float;
end file1;

package body file1 is
         function "-"(L: My_Float) return My_Float is
         begin return L-1.0; end "-";
end file1;

with file1; use file1;
with Ada.Text_IO; use Ada.Text_IO;
procedure file2 is
	X : file1.My_Float := -1.0;
         function "-"(L: My_Float) return My_Float is
         begin return L+1.0; end "-";
         Y : file1.My_Float := -1.0;
begin
         if X /= Y then Put_Line("Correct"); end if;
end file2;

f:\Ada>gnatmake file2
gnatmake file2
gcc -c file2.adb
gcc -c file1.adb
gnatbind -x file2.ali
gnatlink file2.ali

f:\Ada>file2
file2
Correct

Now in one sense this is a pretty silly example.  But it is the way the 
visibility and overloading rules work in Ada for good reasons that have 
nothing to do with this example. ;-)  Obviously it is better to have one 
set of visibility rules for all subprograms than for programmers to try 
to remember which set of visibility rules apply in this case.  (Yes, 
there is a different set of rules for basic operations like numeric 
literals and assignment.  But since these are not overloadable, this 
doesn't cause a problem.)

Finally, there is actually a third way to make the negation operator 
from file1 visible.  But note that this is direct visibility not use 
visible:
   function "-"(L: My_Float) return My_Float renames file1."-";



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

* Re: Negative float problem
  2005-10-27  8:05   ` Robert I. Eachus
@ 2005-10-27 14:48     ` Robert A Duff
  2005-10-27 15:07       ` Maciej Sobczak
  2005-10-27 18:33       ` Dmitry A. Kazakov
  0 siblings, 2 replies; 47+ messages in thread
From: Robert A Duff @ 2005-10-27 14:48 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@comcast.net> writes:

> Robert A Duff wrote:
> 
> > But I suggest using the first solution.  Really, the "use type"
> > semantics ought to be turned on by default -- you shouldn't have to say
> > anything special to use the "-" operator.  After all, you don't have
> > to say anything special to use "1.0" or ":=" on this type!
> 
> There was an Ada83 AI on this, usually referred to as the "for I in
> 1..-10" problem.  (Yes the loop would be executed zero times, but the
> problem is that an Ada 83 compiler was required to reject the for
> statement.)

A more realistic example is "for I in -10 .. 10".  ;-)

But that's a completely separate issue from what the OP asked about.
The problem here is that Ada makes the type default to
Integer.  That's a kludge.  I would simply require the
user to write "for I in Integer range -10..10", if they
want Integer.  But you almost never want Integer -- you should
be declaring a new integer type to suit your purpose.
We've got a default that makes a poor coding practise easier!

And you almost never want -10..10 -- 'Range is far more common.

>...Tucker came up with some preference rules that handle some
> of the cases, but the case mentioned here is one of the more refractory
> ones.  It could be solved by having a negation symbol that could be part
> of a numeric literal.

Perhaps.  Would "- 10" and "-10" then have different semantics?!
                  ^
                  | That's a blank.

>...But as long as users are allowed to overload
> operator symbols, the visibility rules will have some edge cases like
> this one.
> 
> For example
> 
> package file1 is
> 
> 	type My_Float is digits 6;
>          function "-"(L: My_Float) return My_Float;
> end file1;
> 
> package body file1 is
>          function "-"(L: My_Float) return My_Float is
>          begin return L-1.0; end "-";
> end file1;
> 
> with file1; use file1;
> with Ada.Text_IO; use Ada.Text_IO;
> procedure file2 is
> 	X : file1.My_Float := -1.0;
>          function "-"(L: My_Float) return My_Float is
>          begin return L+1.0; end "-";
>          Y : file1.My_Float := -1.0;
> begin
>          if X /= Y then Put_Line("Correct"); end if;
> end file2;

The above example is a separate issue.  This anomaly would occur in
exactly the same way, if you erase the "use file1", and change the
language as I suggested (i.e. "use type" happens automatically).
And it would occur in exactly the same way if the "-" functions
were called Mumble instead of "-".

Anyway, the above example is extremely confusing and error prone.
If I ran the circus, both calls to "-" would be ambiguous,
and therefore illegal.  And the same would apply if they
were called Mumble.

And besides, the OP had no desire to overload any operators!
It's always annoying when somebody wants to do some simple
thing, and the answer from language lawyers is, "Well,
if you added an upside-down generic discriminated task aggregate
to the program, it would cause so-and-so anomaly."

> Now in one sense this is a pretty silly example.  But it is the way the
> visibility and overloading rules work in Ada for good reasons that have
> nothing to do with this example. ;-)  Obviously it is better to have one
> set of visibility rules for all subprograms than for programmers to try
> to remember which set of visibility rules apply in this case.

I agree that it would complicate the language to have different
visibility rules for operators than for other things.  But it would
make the language more friendly.  And the added complexity would
be _less_ than the complexity we caused when we added "use type"
to the language!

>...(Yes,
> there is a different set of rules for basic operations like numeric
> literals and assignment.  But since these are not overloadable, this
> doesn't cause a problem.)
> 
> Finally, there is actually a third way to make the negation operator
> from file1 visible.  But note that this is direct visibility not use
> visible:
>    function "-"(L: My_Float) return My_Float renames file1."-";

That one is error prone, too.  The problem here is that you don't want
to rename anything, so using "renames" is overkill.  The thing is still
called "-" -- you don't want to rename it, you want to import it with
the same name it always had.  Ada has no such feature.

The above sort of renaming was common for operators in Ada 83,
because there was no "use type".  I remember a bug that looked
something like this:

    function "and"(...) return ... renames "and";
    function "or"(...) return ... renames "or";
    function "xor"(...) return ... renames "and";

I was so annoyed by this bug that I still remember it many years later!

Here's another annoying example:

    while X /= null loop...

Null is visible everywhere, but I have to type in extra mumbo jumbo to
see "/=".

- Bob



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

* Re: Negative float problem
  2005-10-27 14:48     ` Robert A Duff
@ 2005-10-27 15:07       ` Maciej Sobczak
  2005-10-27 15:47         ` Robert A Duff
  2005-10-27 18:33       ` Dmitry A. Kazakov
  1 sibling, 1 reply; 47+ messages in thread
From: Maciej Sobczak @ 2005-10-27 15:07 UTC (permalink / raw)


Robert A Duff wrote:

> The problem here is that you don't want
> to rename anything, so using "renames" is overkill.  The thing is still
> called "-" -- you don't want to rename it, you want to import it with
> the same name it always had.  Ada has no such feature.

What about Argument-Dependent Lookup (C++ has it)?

The file1 package was "withed", which makes the type accessible. If the 
compiler is smart enough to figure out the expected type of literal, 
then it should be also smart enough to look up any operators (and why 
not other operations as well?) that are used together with the literal 
in the package from which the expected type come from. That would 
provide the "expected" functionality.

I'm really surprised that the code posted at the beginning of this 
thread does not compile. I'm pretty sure that something like ADL was 
considered for Ada, but apparently rejected. What was the reason?


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-10-27 15:07       ` Maciej Sobczak
@ 2005-10-27 15:47         ` Robert A Duff
  2005-10-28  8:34           ` Maciej Sobczak
  0 siblings, 1 reply; 47+ messages in thread
From: Robert A Duff @ 2005-10-27 15:47 UTC (permalink / raw)


Maciej Sobczak <no.spam@no.spam.com> writes:

> Robert A Duff wrote:
> 
> > The problem here is that you don't want
> > to rename anything, so using "renames" is overkill.  The thing is still
> > called "-" -- you don't want to rename it, you want to import it with
> > the same name it always had.  Ada has no such feature.
> 
> What about Argument-Dependent Lookup (C++ has it)?

What's ADL?  I'm reasonably fluent in C++, but I don't know that term.
Also, can you give an example?

My understanding is that C++ and Ada work roughly the same way,
from a bird's eye view -- there's a notion of what names are
visible where, and then there are overload resolution rules
that determine what denotes what based on argument types and so forth.

> The file1 package was "withed", which makes the type accessible. If the
> compiler is smart enough to figure out the expected type of literal,
> then it should be also smart enough to look up any operators (and why
> not other operations as well?) that are used together with the literal
> in the package from which the expected type come from. That would
> provide the "expected" functionality.

It's not particularly an issue of how smart the compiler is.
Certainly, if the rules were as you suggest, compilers could
implement them just as easily as the current rules.  In fact,
the rules you suggest are equivalent to always having a use clause,
if I understand what you mean.

As to "why not other operations as well?" -- I think it's reasonable to
require a use clause to get them.  And in many cases, it's useful to
avoid the use clause, and use Package_Name.Procedure_Name notation,
because that allows the reader to understand where Procedure_Name
comes from.

Operators are special, though.  They are deliberately meant for cases
where terseness wins over verbosity.  I think Package_Name."-"
is an abomination -- if you want to use that verbose notation,
then you shouldn't have called the thing "-" in the first
place!

Note that in C++, you will generally be referring to an object name as a
prefix, which somewhat mimics the Ada "Package_Name." idea.

> I'm really surprised that the code posted at the beginning of this
> thread does not compile.

Many people are.

>... I'm pretty sure that something like ADL was
> considered for Ada, but apparently rejected. What was the reason?

- Bob



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

* Re: Negative float problem
  2005-10-27 14:48     ` Robert A Duff
  2005-10-27 15:07       ` Maciej Sobczak
@ 2005-10-27 18:33       ` Dmitry A. Kazakov
  1 sibling, 0 replies; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-10-27 18:33 UTC (permalink / raw)


On 27 Oct 2005 10:48:24 -0400, Robert A Duff wrote:

> A more realistic example is "for I in -10 .. 10".  ;-)
> 
> But that's a completely separate issue from what the OP asked about.
> The problem here is that Ada makes the type default to
> Integer.  That's a kludge.

Right. It could be a "universal [integer] range" instead, so that within
the loop "I" would be a universal integer.

> I would simply require the
> user to write "for I in Integer range -10..10", if they
> want Integer.

I suppose, if "I" were universal, type specification would not be required.

>>...Tucker came up with some preference rules that handle some
>> of the cases, but the case mentioned here is one of the more refractory
>> ones.  It could be solved by having a negation symbol that could be part
>> of a numeric literal.
> 
> Perhaps.  Would "- 10" and "-10" then have different semantics?!
>                   ^
>                   | That's a blank.

-(-(-10))

>>...(Yes,
>> there is a different set of rules for basic operations like numeric
>> literals and assignment.  But since these are not overloadable, this
>> doesn't cause a problem.)
>> 
>> Finally, there is actually a third way to make the negation operator
>> from file1 visible.  But note that this is direct visibility not use
>> visible:
>>    function "-"(L: My_Float) return My_Float renames file1."-";
> 
> That one is error prone, too.  The problem here is that you don't want
> to rename anything, so using "renames" is overkill.  The thing is still
> called "-" -- you don't want to rename it, you want to import it with
> the same name it always had.  Ada has no such feature.

Right. There is no way to have "use" transitive. I often need to combine
specifications of several packages in the specification of a third package
which then could be "with/use"-ed. The only way to do it is to rename all
and everything in that specification. It is clumsy and error prone. Then
because renaming was designed improperly in Ada, when the source packages
occasionally get "use"-ed, names hide each other. With generics, tracking
such errors becomes a nightmare.

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



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

* Re: Negative float problem
  2005-10-27 15:47         ` Robert A Duff
@ 2005-10-28  8:34           ` Maciej Sobczak
  2005-10-29 23:39             ` Brian May
  2005-10-30  9:11             ` Dmitry A. Kazakov
  0 siblings, 2 replies; 47+ messages in thread
From: Maciej Sobczak @ 2005-10-28  8:34 UTC (permalink / raw)


Robert A Duff wrote:

>>What about Argument-Dependent Lookup (C++ has it)?
> 
> What's ADL?  I'm reasonably fluent in C++, but I don't know that term.

Which means that the feature is well designed. ;-)

> Also, can you give an example?

Sure.

#include <iostream>

int main()
{
     std::cout << "Hello!\n";
}

Above, iostream was #included, but there is no "using namespace std;" in 
the code. The result is that you have to qualify cout (so that you have 
to write std::cout), but at the same time you don't have to qualify the 
operator<<, even though it is also defined in namespace std and is 
otherwise *not* directly visible.

Basically, the function (and operator) names are *additionally* looked 
up in those namespaces where their parameters are declared. This is 
usefull for operators like above (and certainly applies to the original 
Ada problem in this thread), but can also help with normal functions.

Without this feature, you would have to write:

std::operator<<(std::cout, "Hello\n");

which obviously is not what is wanted.

> It's not particularly an issue of how smart the compiler is.
> Certainly, if the rules were as you suggest, compilers could
> implement them just as easily as the current rules.  In fact,
> the rules you suggest are equivalent to always having a use clause,
> if I understand what you mean.

No, it is not like this. It is an extension of the lookup mechanism, not 
the implicit use clause.

> As to "why not other operations as well?" -- I think it's reasonable to
> require a use clause to get them.

If you allow ADL for operators, it is reasonable to allow it for all 
functions and procedures. There is no point in complicating rules and 
creating further special cases.

> And in many cases, it's useful to
> avoid the use clause, and use Package_Name.Procedure_Name notation,
> because that allows the reader to understand where Procedure_Name
> comes from.

Absolutely. ADL is *not* an implicit use clause and is used in those 
places, where it significantly helps rather than obscuring the code.
And nobody prevents you from writing fully qualified names even when it 
is not necessary, but you find it to improve the readability of the code.

> Note that in C++, you will generally be referring to an object name as a
> prefix, which somewhat mimics the Ada "Package_Name." idea.

Note that in C++ there are also free functions, which use objects as 
their arguments (in fact, the operator<< for ostream falls into this 
category). This is exactly where ADL is supposed to help (and it cannot 
be used anywhere else for that matter, so it does not kick in where it's 
not wanted).

>>I'm really surprised that the code posted at the beginning of this
>>thread does not compile.
> 
> Many people are.

So - why not having ADL in Ada? :)


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-10-28  8:34           ` Maciej Sobczak
@ 2005-10-29 23:39             ` Brian May
  2005-10-30  9:11             ` Dmitry A. Kazakov
  1 sibling, 0 replies; 47+ messages in thread
From: Brian May @ 2005-10-29 23:39 UTC (permalink / raw)


>>>>> "Maciej" == Maciej Sobczak <no.spam@no.spam.com> writes:

    Maciej> So - why not having ADL in Ada? :)

What about the new OO syntax in Ada2005, does that not count as ADL?
-- 
Brian May <bam@snoopy.apana.org.au>



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

* Re: Negative float problem
  2005-10-28  8:34           ` Maciej Sobczak
  2005-10-29 23:39             ` Brian May
@ 2005-10-30  9:11             ` Dmitry A. Kazakov
  2005-10-31  9:46               ` Maciej Sobczak
  1 sibling, 1 reply; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-10-30  9:11 UTC (permalink / raw)


On Fri, 28 Oct 2005 10:34:03 +0200, Maciej Sobczak wrote:

> So - why not having ADL in Ada? :)

C++ compiler matches things bottom up. This is not sufficient for Ada which
represents a more general case. So ADL might be more problematic in Ada.
Much depends on what kind of prefix can stay left of the name. Then in Ada
"." and "::" are overloaded. Further, parameterless function call is
indistinguishable from name.

Personally, I'd prefer simpler visibility rules and more consistency checks
preventing operation hiding, so than one could just "use" almost
everything. Ada's advantage of having packages instead of wild insertions
through #include, should be better used, IMO.

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



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

* Re: Negative float problem
  2005-10-30  9:11             ` Dmitry A. Kazakov
@ 2005-10-31  9:46               ` Maciej Sobczak
  2005-10-31 14:20                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 47+ messages in thread
From: Maciej Sobczak @ 2005-10-31  9:46 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

>>So - why not having ADL in Ada? :)
> 
> C++ compiler matches things bottom up. This is not sufficient for Ada which
> represents a more general case. So ADL might be more problematic in Ada.

I don't really understand this.

> Further, parameterless function call is
> indistinguishable from name.

So? ADL is about *arguments* and does not apply to parameterless 
functions at all. It is there so that "things work as expected", which 
in particular applies to the original problem in this thread. There is 
an operator which does not work "as expected". ADL seems to be a solution.

> Personally, I'd prefer simpler visibility rules and more consistency checks
> preventing operation hiding, so than one could just "use" almost
> everything. Ada's advantage of having packages instead of wild insertions
> through #include, should be better used, IMO.

I don't understand this. Could you please elaborate?
(I'm learning Ada.)


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-10-31  9:46               ` Maciej Sobczak
@ 2005-10-31 14:20                 ` Dmitry A. Kazakov
  2005-11-01 11:06                   ` Maciej Sobczak
  0 siblings, 1 reply; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-10-31 14:20 UTC (permalink / raw)


On Mon, 31 Oct 2005 10:46:06 +0100, Maciej Sobczak wrote:

> Dmitry A. Kazakov wrote:
> 
>>>So - why not having ADL in Ada? :)
>> 
>> C++ compiler matches things bottom up. This is not sufficient for Ada which
>> represents a more general case. So ADL might be more problematic in Ada.
> 
> I don't really understand this.

Basically you want to deduce the operations from their operands. So the
operands should be known before you are going to match the alternatives.
The idea of ADL is that operands determine the matching context. It works
good only if there is a very limited number of such contexts to consider.
Not that a compiler could not crunch that. The problem is that nobody would
be able to describe the game rules, understand them, and even less, predict
the outcome.

>> Further, parameterless function call is
>> indistinguishable from name.
> 
> So? ADL is about *arguments* and does not apply to parameterless 
> functions at all.

But in A.B.C (argument) you do not know whether B is a package, function
name or variable.

> It is there so that "things work as expected", which 
> in particular applies to the original problem in this thread. There is 
> an operator which does not work "as expected". ADL seems to be a solution.

Some legal code might become illegal, because some invisible before
operations would contribute to overloading. [ Of course one can "stratify"
visibility rules to make it a total mess.]

>> Personally, I'd prefer simpler visibility rules and more consistency checks
>> preventing operation hiding, so than one could just "use" almost
>> everything. Ada's advantage of having packages instead of wild insertions
>> through #include, should be better used, IMO.
> 
> I don't understand this. Could you please elaborate?
> (I'm learning Ada.)

People tend to avoid "use" because it leads to ambiguities and mutual
hiding. There are few ways to manage the visibility. Trivial things require
a lot of acrobatics, like combining specifications of two packages into a
third pure package. That is the root of evil. The language should be more
"use" friendly.

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



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

* Re: Negative float problem
  2005-10-31 14:20                 ` Dmitry A. Kazakov
@ 2005-11-01 11:06                   ` Maciej Sobczak
  2005-11-01 14:06                     ` Robert A Duff
  2005-11-01 14:27                     ` Dmitry A. Kazakov
  0 siblings, 2 replies; 47+ messages in thread
From: Maciej Sobczak @ 2005-11-01 11:06 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

>>>Further, parameterless function call is
>>>indistinguishable from name.
>>
>>So? ADL is about *arguments* and does not apply to parameterless 
>>functions at all.
> 
> But in A.B.C (argument) you do not know whether B is a package, function
> name or variable.

ADL applies only to unqualified names.
The above example does not explain why Ada does not have ADL, because it 
is not more complicated than what is there in C++ anyway - in 
particular, with overloaded function call operators and overloaded 
dereference operators the expression A.B->C(argument) may have many 
meanings as well and I don't see in what way Ada represents a more 
general case here.
The important thing is that ADL is *not* used in such cases.

Let's consider again the original problem stated in this thread. The 
operator name is unqualified and finding it in the namespace (package) 
associated with its argument is not a rocket science. It is what the 
programmer expects.

> Some legal code might become illegal, because some invisible before
> operations would contribute to overloading.

Could you please give an example of such code?

Remember that we're considering unqualified names. Note also that ADL is 
performed *only* when the normal lookup fails (it's an extension 
mechanism). This means that by adding ADL to the language you cannot 
break existing code - but you can make some code working that was not 
working before. For example the code from the beginning of this thread.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-11-01 11:06                   ` Maciej Sobczak
@ 2005-11-01 14:06                     ` Robert A Duff
  2005-11-01 14:46                       ` Martin Dowie
  2005-11-01 15:12                       ` Maciej Sobczak
  2005-11-01 14:27                     ` Dmitry A. Kazakov
  1 sibling, 2 replies; 47+ messages in thread
From: Robert A Duff @ 2005-11-01 14:06 UTC (permalink / raw)


Maciej Sobczak <no.spam@no.spam.com> writes:

> [...stuff about ADL]

I'm not sure precisely what you mean by ADL in the Ada context.
Can you state the exact rules?  My gut feel is that ADL does
not make sense for Ada, because Ada has with_clauses, unlike C++.

Example:

    package P1 is
        type T is ...;
        procedure Q(X: T);
    end P1;

    package P2 is
        Mumble: T;
        procedure Q(X: T);
    end P2;

Q(P2.Mumble);

Now which Q are you advocating should be visible here?  Or both?

> Dmitry A. Kazakov wrote:
> 
> >>>Further, parameterless function call is
> >>>indistinguishable from name.
> >>
> >> So? ADL is about *arguments* and does not apply to parameterless
> >> functions at all.
> > But in A.B.C (argument) you do not know whether B is a package,
> > function
> > name or variable.
> 
> ADL applies only to unqualified names.
> The above example does not explain why Ada does not have ADL, because it
> is not more complicated than what is there in C++ anyway - in
> particular, with overloaded function call operators and overloaded
> dereference operators the expression A.B->C(argument) may have many
> meanings as well and I don't see in what way Ada represents a more
> general case here.
> The important thing is that ADL is *not* used in such cases.

I think Dmitry's point is that overload resolution in Ada is both
bottom-up and top-down.  It's simpler in C++ -- just bottom-up.

    type Color is (Red, Blue);
    type Traffic_Light is (Green, Amber, Red);
    procedure P(Param: Color);

    P(Red);

This is legal in Ada.  The compiler knows which Red is meant
based on the expected type for Param.  Similar things are
illegal in C++ (I think -- am I right?).

So if you add ADL to Ada, what would this mean:

    package P1 is
        type T is
            record
                Comp: Integer;
            end record;
        function F(X: Integer) return T;
    end P1;

    package P2 is
        type T is
            record
                Comp: Boolean;
            end record;
        function F(X: Boolean) return T;
        Mumble: Boolean;
    end P2;

    X: Boolean := F(P2.Mumble).Comp;
?

> Let's consider again the original problem stated in this thread. The
> operator name is unqualified and finding it in the namespace (package)
> associated with its argument is not a rocket science. It is what the
> programmer expects.

I agree that a reasonable programmer might expect operators to be
visible in that example.  But we could achieve that very simply:
just make operators visible wherever their type is in scope.
That is, make the "use type" semantics be the default.
No need for the complexity of ADL.

On the other hand, if you want subprograms named by identifiers, as
opposed to operators, to be visible in this manner, then I think I don't
agree that "It is what the programmer expects."  I think there's some
advantage in requiring either dot notation or a use_clause.

I understand that having different rules for operators than for
identifiers adds complexity to the language.  But I think it's
worth it.  Operators really are different, conceptually.
(If that weren't true, we'd use Lisp syntax!)
Anyway, it would not add as much complexity as adding the "use type"
clause, which is, IMHO, an ugly kludge.

> > Some legal code might become illegal, because some invisible before
> > operations would contribute to overloading.
> 
> Could you please give an example of such code?
> 
> Remember that we're considering unqualified names. Note also that ADL is
> performed *only* when the normal lookup fails (it's an extension
> mechanism).

Ahah!  I didn't understand that.  In this case, it would cause
Beaujolais effects, which completely rules it out, for me.

>... This means that by adding ADL to the language you cannot
> break existing code - but you can make some code working that was not
> working before. For example the code from the beginning of this thread.

- Bob



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

* Re: Negative float problem
  2005-11-01 11:06                   ` Maciej Sobczak
  2005-11-01 14:06                     ` Robert A Duff
@ 2005-11-01 14:27                     ` Dmitry A. Kazakov
  2005-11-01 15:19                       ` Maciej Sobczak
  1 sibling, 1 reply; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-11-01 14:27 UTC (permalink / raw)


On Tue, 01 Nov 2005 12:06:19 +0100, Maciej Sobczak wrote:

> Dmitry A. Kazakov wrote:
> 
>>>>Further, parameterless function call is
>>>>indistinguishable from name.
>>>
>>>So? ADL is about *arguments* and does not apply to parameterless 
>>>functions at all.
>> 
>> But in A.B.C (argument) you do not know whether B is a package, function
>> name or variable.
> 
> ADL applies only to unqualified names.

A.B.C is a qualified name, or can be, or not.

>> Some legal code might become illegal, because some invisible before
>> operations would contribute to overloading.
> 
> Could you please give an example of such code?

package A is
   X : Integer;
end A;

package B is
   X : Integer;
   function "+" (Left, Right : Integer)  return Integer;
end B;

with A, B;
...
A.X + B.X  -- Unambiguous now
 
> Remember that we're considering unqualified names. Note also that ADL is 
> performed *only* when the normal lookup fails (it's an extension 
> mechanism).

I mentioned in my previous post that stratified visibility rules is a
kludge. And anyway it will not work as the example below shows:

package A is
   X : Integer;
   function "+" (Left, Right : Integer)  return Integer;
end A;

package B is
   X : Integer;
   function "+" (Left, Right : Integer)  return Integer;
end B;

with A, B;
...
A.X + B.X

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



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

* Re: Negative float problem
  2005-11-01 14:06                     ` Robert A Duff
@ 2005-11-01 14:46                       ` Martin Dowie
  2005-11-01 16:04                         ` Hyman Rosen
  2005-11-02  0:13                         ` Robert A Duff
  2005-11-01 15:12                       ` Maciej Sobczak
  1 sibling, 2 replies; 47+ messages in thread
From: Martin Dowie @ 2005-11-01 14:46 UTC (permalink / raw)


Robert A Duff wrote:
> I think Dmitry's point is that overload resolution in Ada is both
> bottom-up and top-down.  It's simpler in C++ -- just bottom-up.
>
>     type Color is (Red, Blue);
>     type Traffic_Light is (Green, Amber, Red);
>     procedure P(Param: Color);
>
>     P(Red);
>
> This is legal in Ada.  The compiler knows which Red is meant
> based on the expected type for Param.  Similar things are
> illegal in C++ (I think -- am I right?).

Yup, you can't have overloaded enumeration values - I guess because they are
really just 'int', so which one would you mean?

Cheers

-- Martin






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

* Re: Negative float problem
  2005-11-01 14:06                     ` Robert A Duff
  2005-11-01 14:46                       ` Martin Dowie
@ 2005-11-01 15:12                       ` Maciej Sobczak
  2005-11-02  0:28                         ` Robert A Duff
  1 sibling, 1 reply; 47+ messages in thread
From: Maciej Sobczak @ 2005-11-01 15:12 UTC (permalink / raw)


Robert A Duff wrote:

> I'm not sure precisely what you mean by ADL in the Ada context.
> Can you state the exact rules?  My gut feel is that ADL does
> not make sense for Ada, because Ada has with_clauses, unlike C++.
> 
> Example:
> 
>     package P1 is
>         type T is ...;
>         procedure Q(X: T);
>     end P1;
> 
>     package P2 is
>         Mumble: T;
>         procedure Q(X: T);
>     end P2;
> 
> Q(P2.Mumble);
> 
> Now which Q are you advocating should be visible here?  Or both?

Above, if only you make T visible for P2 (otherwise P2 should not even 
compile), then it is P1.Q which should be called. It is the *type* of 
the parameter that guides the lookup, just as elsewhere.

The same example can be restated in C++ as follows:

namespace P1
{
      struct T {};
      void Q(T X);
}

namespace P2
{
      using namespace P1; // you missed the equivalent of this line

      T Mumble;
      void Q(T X);
}

int main()
{
      Q(P2::Mumble);
}


> I think Dmitry's point is that overload resolution in Ada is both
> bottom-up and top-down.  It's simpler in C++ -- just bottom-up.
> 
>     type Color is (Red, Blue);
>     type Traffic_Light is (Green, Amber, Red);
>     procedure P(Param: Color);
> 
>     P(Red);
> 
> This is legal in Ada.  The compiler knows which Red is meant
> based on the expected type for Param.

And I like it.

> Similar things are
> illegal in C++ (I think -- am I right?).

Similar things do not exist in C++ because enums are not strongly typed 
(there is a proposal for strongly typed enums, however) and because 
functions do not overload on their return type. This behaviour can be 
implemented by user in terms of overloading cast operator for the given 
set of types, but this is rarely used, if ever.
It's considered to be obscure and error prone. :)

> So if you add ADL to Ada, what would this mean:
> 
>     package P1 is
>         type T is
>             record
>                 Comp: Integer;
>             end record;
>         function F(X: Integer) return T;
>     end P1;
> 
>     package P2 is
>         type T is
>             record
>                 Comp: Boolean;
>             end record;
>         function F(X: Boolean) return T;
>         Mumble: Boolean;
>     end P2;
> 
>     X: Boolean := F(P2.Mumble).Comp;
> ?

I'd expect this code to fail to compile, because:
- F is not directly visible at the call site, because there is no "use" 
clause that would bring it from either P1 or P2, *AND*
- P2.Mumble is of type Boolean and there is no F in the package where 
Boolean is defined.

As stated previously, ADL is guided by types, not by objects.


>>Let's consider again the original problem stated in this thread.
> 
> I agree that a reasonable programmer might expect operators to be
> visible in that example.  But we could achieve that very simply:
> just make operators visible wherever their type is in scope.

Only operators?

> That is, make the "use type" semantics be the default.
> No need for the complexity of ADL.
> 
> On the other hand, if you want subprograms named by identifiers, as
> opposed to operators, to be visible in this manner, then I think I don't
> agree that "It is what the programmer expects."  I think there's some
> advantage in requiring either dot notation or a use_clause.

I agree, otherwise there would be no advantage of having packages (or 
namespaces) at all. But with ADL you *have* to name at least one entity 
in the whole expression (or in a declaration or whatever is the context) 
in a way that makes it clear what package (or namespace) it belongs to. 
In the context of the original problem, it was the name of the type: 
file1.My_Float. Why qualifying the operator in addition to that?

> I understand that having different rules for operators than for
> identifiers adds complexity to the language.  But I think it's
> worth it.  Operators really are different, conceptually.
> (If that weren't true, we'd use Lisp syntax!)

If you ask me, then no, syntax has nothing to do with conceptual 
differences. :)


>>Remember that we're considering unqualified names. Note also that ADL is
>>performed *only* when the normal lookup fails (it's an extension
>>mechanism).
> 
> Ahah!  I didn't understand that.  In this case, it would cause
> Beaujolais effects, which completely rules it out, for me.

Sorry, I've just checked more carefully and I messed things up before.

The set of declarations which are taken into account is the *union* of 
those from "ordinary" lookup and those from ADL, which means that the 
additional set of names is considered anyway.
This means that indeed, it cannot be added to the language without 
possibly breaking some existing code. ADL has to be there from the 
beginning.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-11-01 14:27                     ` Dmitry A. Kazakov
@ 2005-11-01 15:19                       ` Maciej Sobczak
  2005-11-01 19:44                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 47+ messages in thread
From: Maciej Sobczak @ 2005-11-01 15:19 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

>>>Some legal code might become illegal, because some invisible before
>>>operations would contribute to overloading.
>>
>>Could you please give an example of such code?
> 
> package A is
>    X : Integer;
> end A;
> 
> package B is
>    X : Integer;
>    function "+" (Left, Right : Integer)  return Integer;
> end B;
> 
> with A, B;
> ...
> A.X + B.X  -- Unambiguous now

This example do not consider ADL, because ADL is guided by types, not by 
objects - here, Integer is defined in package Standard and therefore 
only this package would additionally contribute to the lookup. The same 
for the other example from your post.

Note that indeed (see my reply to Robert A Duff) adding ADL would either 
break some existing code or introduce Beaujolais effects. ADL has to be 
there as the integrated part of the package (or namespace) concept and 
cannot be added as an afterthought.

Interesting discussion, though. :)

-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-11-01 14:46                       ` Martin Dowie
@ 2005-11-01 16:04                         ` Hyman Rosen
  2005-11-01 17:19                           ` Martin Dowie
  2005-11-02  0:13                         ` Robert A Duff
  1 sibling, 1 reply; 47+ messages in thread
From: Hyman Rosen @ 2005-11-01 16:04 UTC (permalink / raw)


Martin Dowie wrote:
> Yup, you can't have overloaded enumeration values
> I guess because they are really just 'int', so which
> one would you mean?

No, that's not why. Enumerators have the type of their
enumeration. But enumerators go into their enclosing
namespace or class, so having multiple ones causes name
conflicts. You can actually simulate Ada's approach in
C++ by hand, as I show below. You can probably reduce
the boilerplate even more by using the Boost preprocessor
library, and that would also let you automatically get
string versions of the enumerators like Ada has.

#include <iostream>
#include <ostream>

struct Color { enum E { Red, Blue }; typedef E (&e)(E); };
struct Traffic_Light { enum E { Green, Amber, Red }; typedef E (&e)(E);
};

#define EDEF(C,e) C::E e(C::E = C::e) { return C::e; }
EDEF(Color, Red)
EDEF(Color, Blue)
EDEF(Traffic_Light, Green)
EDEF(Traffic_Light, Amber)
EDEF(Traffic_Light, Red)

void f_c(Color::e v)
 { std::cout << "Color: " << v(Color::E()) << "\n"; }
void f_t(Traffic_Light::e v)
 { std::cout << "Traffic_Light: " << v(Traffic_Light::E()) << "\n"; }

// Notice there are two Reds defined at global scope with no conflict
// and that each function is called with the proper Red.
int main() { f_c(Red); f_t(Red); }




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

* Re: Negative float problem
  2005-11-01 16:04                         ` Hyman Rosen
@ 2005-11-01 17:19                           ` Martin Dowie
  0 siblings, 0 replies; 47+ messages in thread
From: Martin Dowie @ 2005-11-01 17:19 UTC (permalink / raw)


Hyman Rosen wrote:
> Martin Dowie wrote:
> 
>>Yup, you can't have overloaded enumeration values
>>I guess because they are really just 'int', so which
>>one would you mean?
> 
> 
> No, that's not why. Enumerators have the type of their
> enumeration. But enumerators go into their enclosing
> namespace or class, so having multiple ones causes name
> conflicts. You can actually simulate Ada's approach in
> C++ by hand, as I show below. You can probably reduce
> the boilerplate even more by using the Boost preprocessor
> library, and that would also let you automatically get
> string versions of the enumerators like Ada has.
> 
> #include <iostream>
> #include <ostream>
> 
> struct Color { enum E { Red, Blue }; typedef E (&e)(E); };
> struct Traffic_Light { enum E { Green, Amber, Red }; typedef E (&e)(E);
> };
> 
> #define EDEF(C,e) C::E e(C::E = C::e) { return C::e; }
> EDEF(Color, Red)
> EDEF(Color, Blue)
> EDEF(Traffic_Light, Green)
> EDEF(Traffic_Light, Amber)
> EDEF(Traffic_Light, Red)
> 
> void f_c(Color::e v)
>  { std::cout << "Color: " << v(Color::E()) << "\n"; }
> void f_t(Traffic_Light::e v)
>  { std::cout << "Traffic_Light: " << v(Traffic_Light::E()) << "\n"; }
> 
> // Notice there are two Reds defined at global scope with no conflict
> // and that each function is called with the proper Red.
> int main() { f_c(Red); f_t(Red); }
> 

Thanks for that...

...although I might add this example to the list of reasons I really 
can't be bothered with C++ : what a palaver!!! ;-)



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

* Re: Negative float problem
  2005-11-01 15:19                       ` Maciej Sobczak
@ 2005-11-01 19:44                         ` Dmitry A. Kazakov
  2005-11-02  9:04                           ` Maciej Sobczak
  0 siblings, 1 reply; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-11-01 19:44 UTC (permalink / raw)


On Tue, 01 Nov 2005 16:19:16 +0100, Maciej Sobczak wrote:

> Dmitry A. Kazakov wrote:
> 
>>>>Some legal code might become illegal, because some invisible before
>>>>operations would contribute to overloading.
>>>
>>>Could you please give an example of such code?
>> 
>> package A is
>>    X : Integer;
>> end A;
>> 
>> package B is
>>    X : Integer;
>>    function "+" (Left, Right : Integer)  return Integer;
>> end B;
>> 
>> with A, B;
>> ...
>> A.X + B.X  -- Unambiguous now
> 
> This example do not consider ADL, because ADL is guided by types, not by 
> objects - here, Integer is defined in package Standard and therefore 
> only this package would additionally contribute to the lookup.

package A is
   type Foo is ...;
end A;
-------------------
package A.B is
   X : Foo;
   function "+" (Left, Right : Foo)  return Foo;
end A.B;
------------------
with A.B;
...
A.B.X + A.B.X  -- Why this does not work?

And now consider this:

package A is
   type Foo is ...;
   function "+" (Left, Right : Foo)  return Foo;
end A;
-------------------
package A.B is
   X : Foo;
   function "+" (Left, Right : Foo)  return Foo;
end A.B;
------------------
with A.B;
...
A.B.X + A.B.X  -- BOOOOM!

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



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

* Re: Negative float problem
  2005-11-01 14:46                       ` Martin Dowie
  2005-11-01 16:04                         ` Hyman Rosen
@ 2005-11-02  0:13                         ` Robert A Duff
  2005-11-02  6:59                           ` Martin Dowie
  1 sibling, 1 reply; 47+ messages in thread
From: Robert A Duff @ 2005-11-02  0:13 UTC (permalink / raw)


"Martin Dowie" <martin.dowie@baesystems.com> writes:

> Robert A Duff wrote:
> > I think Dmitry's point is that overload resolution in Ada is both
> > bottom-up and top-down.  It's simpler in C++ -- just bottom-up.
> >
> >     type Color is (Red, Blue);
> >     type Traffic_Light is (Green, Amber, Red);
> >     procedure P(Param: Color);
> >
> >     P(Red);
> >
> > This is legal in Ada.  The compiler knows which Red is meant
> > based on the expected type for Param.  Similar things are
> > illegal in C++ (I think -- am I right?).
> 
> Yup, you can't have overloaded enumeration values - I guess because they are
> really just 'int', so which one would you mean?

Sorry.  My post was confusing.

In Ada, enum lits are parameterless functions.  So the corresponding
thing in C++ would be parameterless functions.  So pretend my example
was something like:

    function Red return Color;
    function Blue return Color;
    function Green return Traffic_Light;
    function Amber return Traffic_Light;
    function Red return Traffic_Light;

    procedure P(Param: Color);

    P(Red);

That sort of thing works fine in Ada, but C++ doesn't like it.

I wasn't talking about the difference between enums in C++ versus Ada.
I was talking about the difference in overload resolution rules.
Namely that the result type of a function call is used to resolve
in Ada, but not in C++.  (And by the way Ada has this weird idea
that enum lits are functions.)

- Bob



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

* Re: Negative float problem
  2005-11-01 15:12                       ` Maciej Sobczak
@ 2005-11-02  0:28                         ` Robert A Duff
  2005-11-02  4:16                           ` Steve Whalen
  2005-11-14  7:26                           ` Dave Thompson
  0 siblings, 2 replies; 47+ messages in thread
From: Robert A Duff @ 2005-11-02  0:28 UTC (permalink / raw)


Maciej Sobczak <no.spam@no.spam.com> writes:

> Robert A Duff wrote:
> 
> > I'm not sure precisely what you mean by ADL in the Ada context.
> > Can you state the exact rules?  My gut feel is that ADL does
> > not make sense for Ada, because Ada has with_clauses, unlike C++.
> > Example:
> >     package P1 is
> >         type T is ...;
> >         procedure Q(X: T);
> >     end P1;
> >     package P2 is
> >         Mumble: T;
> >         procedure Q(X: T);
> >     end P2;
> > Q(P2.Mumble);
> > Now which Q are you advocating should be visible here?  Or both?
> 
> Above, if only you make T visible for P2 (otherwise P2 should not even
> compile),...

Right.  It should be "Mumble: P1.T;".  Sorry about that.

>... then it is P1.Q which should be called. It is the *type* of
> the parameter that guides the lookup, just as elsewhere.

OK.

> The same example can be restated in C++ as follows:
> 
> namespace P1
> {
>       struct T {};
>       void Q(T X);
> }
> 
> namespace P2
> {
>       using namespace P1; // you missed the equivalent of this line

Right.  Or "P1::T Mumble;".

>       T Mumble;
>       void Q(T X);
> }
> 
> int main()
> {
>       Q(P2::Mumble);
> }
> 
> 
> > I think Dmitry's point is that overload resolution in Ada is both
> > bottom-up and top-down.  It's simpler in C++ -- just bottom-up.
> >     type Color is (Red, Blue);
> >     type Traffic_Light is (Green, Amber, Red);
> >     procedure P(Param: Color);
> >     P(Red);
> > This is legal in Ada.  The compiler knows which Red is meant
> > based on the expected type for Param.
> 
> And I like it.

Me, too.

> > Similar things are
> > illegal in C++ (I think -- am I right?).
> 
> Similar things do not exist in C++ because enums are not strongly typed

Well, change the enums to parameterless functions, then.  That
illustrates the point, and as I said in another post, I'm sorry
for confusing the issue with enums, which are quite different in the
two languages.

> (there is a proposal for strongly typed enums, however) and because
> functions do not overload on their return type.

Right.  That was my point: functions do not overload on their return
type in C++.

It's the same reason why you have to put an annoying "L" at the end of a
"long int" literal in C++.  That's a kludge, and it wouldn't work at all
in Ada, which has many integer types.  Have I got that right?

>...This behaviour can be
> implemented by user in terms of overloading cast operator for the given
> set of types, but this is rarely used, if ever.
> It's considered to be obscure and error prone. :)
> 
> > So if you add ADL to Ada, what would this mean:
> >     package P1 is
> >         type T is
> >             record
> >                 Comp: Integer;
> >             end record;
> >         function F(X: Integer) return T;
> >     end P1;
> >     package P2 is
> >         type T is
> >             record
> >                 Comp: Boolean;
> >             end record;
> >         function F(X: Boolean) return T;
> >         Mumble: Boolean;
> >     end P2;
> >     X: Boolean := F(P2.Mumble).Comp;
> > ?
> 
> I'd expect this code to fail to compile, because:
> - F is not directly visible at the call site, because there is no "use"
> clause that would bring it from either P1 or P2, *AND*
> - P2.Mumble is of type Boolean and there is no F in the package where
> Boolean is defined.
> 
> As stated previously, ADL is guided by types, not by objects.
> 
> 
> >>Let's consider again the original problem stated in this thread.
> > I agree that a reasonable programmer might expect operators to be
> > visible in that example.  But we could achieve that very simply:
> > just make operators visible wherever their type is in scope.
> 
> Only operators?

Yeah.

> > That is, make the "use type" semantics be the default.
> > No need for the complexity of ADL.
> > On the other hand, if you want subprograms named by identifiers, as
> > opposed to operators, to be visible in this manner, then I think I don't
> > agree that "It is what the programmer expects."  I think there's some
> > advantage in requiring either dot notation or a use_clause.
> 
> I agree, otherwise there would be no advantage of having packages (or
> namespaces) at all. But with ADL you *have* to name at least one entity
> in the whole expression (or in a declaration or whatever is the context)
> in a way that makes it clear what package (or namespace) it belongs
> to. In the context of the original problem, it was the name of the type:
> file1.My_Float. Why qualifying the operator in addition to that?

For operators, I agree.  For identifiers, I'm not so sure.

> > I understand that having different rules for operators than for
> > identifiers adds complexity to the language.  But I think it's
> > worth it.  Operators really are different, conceptually.
> > (If that weren't true, we'd use Lisp syntax!)
> 
> If you ask me, then no, syntax has nothing to do with conceptual
> differences. :)

But if "+" and "Add" are really the same, conceptually, then we should
be willing to write "X := Add(X, 1);", or perhaps "Setq(X, Add(X, 1));".
Which is pretty close to a Lisp-like "(setq x (add x 1))".

> >>Remember that we're considering unqualified names. Note also that ADL is
> >>performed *only* when the normal lookup fails (it's an extension
> >>mechanism).
> > Ahah!  I didn't understand that.  In this case, it would cause
> > Beaujolais effects, which completely rules it out, for me.
> 
> Sorry, I've just checked more carefully and I messed things up before.

Ahah! again.

> The set of declarations which are taken into account is the *union* of
> those from "ordinary" lookup and those from ADL, which means that the
> additional set of names is considered anyway.
> This means that indeed, it cannot be added to the language without
> possibly breaking some existing code. ADL has to be there from the
> beginning.

Yes, it seems one has a choice between Beaujolais effects and
incompatibility.

- Bob



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

* Re: Negative float problem
  2005-11-02  0:28                         ` Robert A Duff
@ 2005-11-02  4:16                           ` Steve Whalen
  2005-11-14  7:26                           ` Dave Thompson
  1 sibling, 0 replies; 47+ messages in thread
From: Steve Whalen @ 2005-11-02  4:16 UTC (permalink / raw)


Robert A Duff wrote:
> Yes, it seems one has a choice between Beaujolais effects and
> incompatibility.
>
> - Bob

Wow. It seems like it's been years since hearing much talk about
Beaujolais effects. Seems like they were a fairly frequent topic
of conversation here some years back.

I wonder if the reduction in traffic on comp.lang.ada about
Beaujolais effects is due to the prevalence of Ada95 compilers
and the Ada95 compiler's ability to declare Beaujolais effects
ambiguous thus warning the programmer?

Steve




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

* Re: Negative float problem
  2005-11-02  0:13                         ` Robert A Duff
@ 2005-11-02  6:59                           ` Martin Dowie
  2005-11-02 13:24                             ` Robert A Duff
  0 siblings, 1 reply; 47+ messages in thread
From: Martin Dowie @ 2005-11-02  6:59 UTC (permalink / raw)


Robert A Duff wrote:
> I wasn't talking about the difference between enums in C++ versus Ada.
> I was talking about the difference in overload resolution rules.
> Namely that the result type of a function call is used to resolve
> in Ada, but not in C++.  (And by the way Ada has this weird idea
> that enum lits are functions.)

I actually rather like this 'weird idea' - it can be very handy with 
generics:

generic
    type Foo is private;
    with function Is_A_Bar (F : Foo) return Boolean;
procedure Generic_Do_Something (F : Foo);

procedure Do_Something is
    new Generic_Do_Something (Integer, True);
    -- Integers are always Bars

procedure Do_Something is
    new Generic_Do_Something (Float, False);
    -- Floats are never Bars

procedure Do_Something is
    new Generic_Do_Something (My_Type, Is_This_A_Bar);
    -- My_Types are sometimes Bars

Cheers

-- Martin



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

* Re: Negative float problem
  2005-11-01 19:44                         ` Dmitry A. Kazakov
@ 2005-11-02  9:04                           ` Maciej Sobczak
  2005-11-02 11:17                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 47+ messages in thread
From: Maciej Sobczak @ 2005-11-02  9:04 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> package A is
>    type Foo is ...;
> end A;
> -------------------
> package A.B is
>    X : Foo;
>    function "+" (Left, Right : Foo)  return Foo;
> end A.B;
> ------------------
> with A.B;
> ...
> A.B.X + A.B.X  -- Why this does not work?

Because "+" is not directly visible.

ADL would not help here, because A.B.X is of type Foo, which is defined 
in A, and there is no "+" defined in this package.


> And now consider this:
> 
> package A is
>    type Foo is ...;
>    function "+" (Left, Right : Foo)  return Foo;
> end A;
> -------------------
> package A.B is
>    X : Foo;
>    function "+" (Left, Right : Foo)  return Foo;
> end A.B;
> ------------------
> with A.B;
> ...
> A.B.X + A.B.X  -- BOOOOM!

Why BOOOOM? It still doesn't work, for the same reason.

With ADL, I would expect it to call A."+". This means that some program, 
which is not legal without ADL, would be legal with ADL in the language.

(If your point is that any language feature can seem obscure when shown 
in obscure examples, then I completely agree.)


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-11-02  9:04                           ` Maciej Sobczak
@ 2005-11-02 11:17                             ` Dmitry A. Kazakov
  2005-11-02 13:03                               ` Maciej Sobczak
                                                 ` (2 more replies)
  0 siblings, 3 replies; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-11-02 11:17 UTC (permalink / raw)


On Wed, 02 Nov 2005 10:04:21 +0100, Maciej Sobczak wrote:

> Dmitry A. Kazakov wrote:
> 
>> package A is
>>    type Foo is ...;
>>    function "+" (Left, Right : Foo)  return Foo;
>> end A;
>> -------------------
>> package A.B is
>>    X : Foo;
>>    function "+" (Left, Right : Foo)  return Foo;
>> end A.B;
>> ------------------
>> with A.B;
>> ...
>> A.B.X + A.B.X  -- BOOOOM!
> 
> With ADL, I would expect it to call A."+".

Which perfectly illustrates why there should be no such thing as ADL.
Exactly to prevent making the above legal with the meaning A."+".

> This means that some program, 
> which is not legal without ADL, would be legal with ADL in the language.
> 
> (If your point is that any language feature can seem obscure when shown 
> in obscure examples, then I completely agree.)

No. The point is that the language should maintain views properly. That is
(here I agree with Robert Duff):

If you see A of T, then you also see T.
If you see T then you also see its primitive operations.
[ and one additional point from me: maybe there should be non-primitive
operations allowed in specifications! ]

Another question is how this language design principle should be mapped
into name spaces, public and private views etc. But to me one thing is
clear, kludges like ADL is not the answer.

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



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

* Re: Negative float problem
  2005-11-02 11:17                             ` Dmitry A. Kazakov
@ 2005-11-02 13:03                               ` Maciej Sobczak
  2005-11-02 14:20                                 ` Jean-Pierre Rosen
  2005-11-02 13:32                               ` Robert A Duff
  2005-11-02 13:47                               ` Dmitry A. Kazakov
  2 siblings, 1 reply; 47+ messages in thread
From: Maciej Sobczak @ 2005-11-02 13:03 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

>>>package A is
>>>   type Foo is ...;
>>>   function "+" (Left, Right : Foo)  return Foo;
>>>end A;
>>>-------------------
>>>package A.B is
>>>   X : Foo;
>>>   function "+" (Left, Right : Foo)  return Foo;
>>>end A.B;
>>>------------------
>>>with A.B;
>>>...
>>>A.B.X + A.B.X  -- BOOOOM!
>>
>>With ADL, I would expect it to call A."+".
> 
> 
> Which perfectly illustrates why there should be no such thing as ADL.
> Exactly to prevent making the above legal with the meaning A."+".

> The point is that the language should maintain views properly.

As I said - I'm learning Ada. I don't know the language to the extent 
that allows me to analyze up-front all its corner cases. The fact that 
simple rules for ADL do not "work" with things like this is not an 
argument for me. I don't expect ADL to take up at most one sentence in 
the language reference (it doesn't in C++ :) ) and I'm sure that with a 
bit of goodwill it is possible to formulate it in a way that is 
consistent with other language elements - *even* if it takes few 
sentences more. The problem is that I'm not ready to do this by myself, 
especially at this stage (and there is no point in doing it, anyway, 
apart from exercising lawyerese).

I treat ADL as a natural and integrated part of the package or namespace 
concept and as a (prospective) language user I'd rather expect it to be 
there and be defined consistently with other language elements than to 
not have it only because people are/were afraid of formulating it with 
other issues in mind.
If Ada can be complex without ADL, then it could be complex with ADL as 
well. :)

As Samuel Tardieu said earlier about the original problem - "... almost 
any Ada-er has learnt this rule the hard way one day or another". For me 
this sentence expresses some defficiency in the language. If programmers 
are bound to having hard rules no matter what, then I'd prefer those 
rules to be easier in 95% cases and more difficult in the remaining 
corners than the other way round.

Just my thoughts. Thanks for discussion anyway, I'm going to learn Ada 
*even* without ADL. ;-)


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-11-02  6:59                           ` Martin Dowie
@ 2005-11-02 13:24                             ` Robert A Duff
  2005-11-02 15:22                               ` Martin Dowie
  0 siblings, 1 reply; 47+ messages in thread
From: Robert A Duff @ 2005-11-02 13:24 UTC (permalink / raw)


Martin Dowie <martin.dowie@btopenworld.com> writes:

> Robert A Duff wrote:
> > I wasn't talking about the difference between enums in C++ versus Ada.
> > I was talking about the difference in overload resolution rules.
> > Namely that the result type of a function call is used to resolve
> > in Ada, but not in C++.  (And by the way Ada has this weird idea
> > that enum lits are functions.)
> 
> I actually rather like this 'weird idea' - it can be very handy with
> generics:
> 
> generic
>     type Foo is private;
>     with function Is_A_Bar (F : Foo) return Boolean;
> procedure Generic_Do_Something (F : Foo);
> 
> procedure Do_Something is
>     new Generic_Do_Something (Integer, True);
>     -- Integers are always Bars
> 
> procedure Do_Something is
>     new Generic_Do_Something (Float, False);
>     -- Floats are never Bars
> 
> procedure Do_Something is
>     new Generic_Do_Something (My_Type, Is_This_A_Bar);
>     -- My_Types are sometimes Bars

Except that the above is illegal.  ;-)  True is a _parameterless_
function, and does not match Is_A_Bar.

Anyway, this rule is a kludge, because it doesn't work for other things
(constants come to mind).  For example:

    type Color is (Red, Orange);

should have similar semantics to:

    type Color is private;
    Red: constant Color;
    Orange: constant Color;
private
    type Color is range ...;
    Red: constant Color := 0;
    Orange: constant Color := 1;

because conceptually, they are similar.  People think of enums as a
restricted form of integers, not as functions.  And if they can be
passed to generic formal functions, then _any_ expression should
allow that functionality.

You should be able to switch back and forth between integers and enums
without arbitrary rules getting in the way.  (There might be good
reasons to use integers, for example -- you want to interface to
some other language.  But when you switch to integers, you have
to change the names of all the overloaded literals.)

Besides, allowing False to be passed to a generic formal function causes
quite a bit of implementation difficulty -- far more than it's worth.

- Bob



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

* Re: Negative float problem
  2005-11-02 11:17                             ` Dmitry A. Kazakov
  2005-11-02 13:03                               ` Maciej Sobczak
@ 2005-11-02 13:32                               ` Robert A Duff
  2005-11-02 14:44                                 ` Dmitry A. Kazakov
  2005-11-02 13:47                               ` Dmitry A. Kazakov
  2 siblings, 1 reply; 47+ messages in thread
From: Robert A Duff @ 2005-11-02 13:32 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Wed, 02 Nov 2005 10:04:21 +0100, Maciej Sobczak wrote:
> 
> > Dmitry A. Kazakov wrote:
> > 
> >> package A is
> >>    type Foo is ...;
> >>    function "+" (Left, Right : Foo)  return Foo;
> >> end A;
> >> -------------------
> >> package A.B is
> >>    X : Foo;
> >>    function "+" (Left, Right : Foo)  return Foo;
> >> end A.B;
> >> ------------------
> >> with A.B;
> >> ...
> >> A.B.X + A.B.X  -- BOOOOM!
> > 
> > With ADL, I would expect it to call A."+".
> 
> Which perfectly illustrates why there should be no such thing as ADL.
> Exactly to prevent making the above legal with the meaning A."+".

Well, perhaps, but the above example is confusing with the current
rules, too.  If you say "use type A.Foo", you get one "+", when you
might expect to get the other.  Even worse, add this to A.B:
"subtype Foo is A.Foo", and then say "use type A.B.Foo" -- you might be
surprised to get A."+".

I think the answer is a coding convention: If you want to declare an
operator, always make it a primitive of the interesting type involved.
I'm not sure whether that could reasonably be a language rule...

- Bob



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

* Re: Negative float problem
  2005-11-02 11:17                             ` Dmitry A. Kazakov
  2005-11-02 13:03                               ` Maciej Sobczak
  2005-11-02 13:32                               ` Robert A Duff
@ 2005-11-02 13:47                               ` Dmitry A. Kazakov
  2 siblings, 0 replies; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-11-02 13:47 UTC (permalink / raw)


On Wed, 2 Nov 2005 12:17:04 +0100, Dmitry A. Kazakov wrote:

> [ and one additional point from me: maybe there should be non-primitive
> operations allowed in specifications! ]
^^^^  Not allowed, I mean.

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



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

* Re: Negative float problem
  2005-11-02 13:03                               ` Maciej Sobczak
@ 2005-11-02 14:20                                 ` Jean-Pierre Rosen
  2005-11-02 20:15                                   ` Jeffrey R. Carter
  2005-11-03  9:51                                   ` Maciej Sobczak
  0 siblings, 2 replies; 47+ messages in thread
From: Jean-Pierre Rosen @ 2005-11-02 14:20 UTC (permalink / raw)


Maciej Sobczak a �crit :
> As Samuel Tardieu said earlier about the original problem - "... almost 
> any Ada-er has learnt this rule the hard way one day or another". For me 
> this sentence expresses some defficiency in the language. If programmers 
> are bound to having hard rules no matter what, then I'd prefer those 
> rules to be easier in 95% cases and more difficult in the remaining 
> corners than the other way round.
> 
Since you are new to Ada, there is something that you must understand. 
The Ada language has been designed in such a way that either a construct 
always works, and works the same with every implementation, or does not 
compile. There is no space for "sometimes", "maybe", "depends", and 
other things like that that are common in other languages.

The price for this is that the user is sometimes frustrated, because it 
seems that something very natural from a user's point of view is 
rejected by the compiler. Quite often, the reason is that the simple 
case would work, but the general one would not. Hence it is always rejected.

In the long run, this is quite reassuring. You get confident in the 
language and the compiler, because you understand that they are there to 
protect you - sometimes from issues that you don't even know about. And 
you will accept the (small) price you have to pay for this.

(Agreed: some discussions on c.l.a. show that not everybody is accepting 
the price :-)

-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



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

* Re: Negative float problem
  2005-11-02 13:32                               ` Robert A Duff
@ 2005-11-02 14:44                                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-11-02 14:44 UTC (permalink / raw)


On 02 Nov 2005 08:32:21 -0500, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On Wed, 02 Nov 2005 10:04:21 +0100, Maciej Sobczak wrote:
>> 
>>> Dmitry A. Kazakov wrote:
>>> 
>>>> package A is
>>>>    type Foo is ...;
>>>>    function "+" (Left, Right : Foo)  return Foo;
>>>> end A;
>>>> -------------------
>>>> package A.B is
>>>>    X : Foo;
>>>>    function "+" (Left, Right : Foo)  return Foo;
>>>> end A.B;
>>>> ------------------
>>>> with A.B;
>>>> ...
>>>> A.B.X + A.B.X  -- BOOOOM!
>>> 
>>> With ADL, I would expect it to call A."+".
>> 
>> Which perfectly illustrates why there should be no such thing as ADL.
>> Exactly to prevent making the above legal with the meaning A."+".
> 
> Well, perhaps, but the above example is confusing with the current
> rules, too.  If you say "use type A.Foo", you get one "+", when you
> might expect to get the other.  Even worse, add this to A.B:
> "subtype Foo is A.Foo", and then say "use type A.B.Foo" -- you might be
> surprised to get A."+".

Because "use type" is also a kludge. (:-))

> I think the answer is a coding convention: If you want to declare an
> operator, always make it a primitive of the interesting type involved.
> I'm not sure whether that could reasonably be a language rule...

I think that non-primitive operations should be outlawed in specifications.
I mean as a language design goal, because this would also require handling
multiple dispatch and operations which are primitive for more than one
type. Then there is a case of class-wide operations...

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



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

* Re: Negative float problem
  2005-11-02 13:24                             ` Robert A Duff
@ 2005-11-02 15:22                               ` Martin Dowie
  0 siblings, 0 replies; 47+ messages in thread
From: Martin Dowie @ 2005-11-02 15:22 UTC (permalink / raw)


Robert A Duff wrote:
> Except that the above is illegal.  ;-)  True is a _parameterless_
> function, and does not match Is_A_Bar.

Yeah, I need to get my Outlook Express-AdaMagic-Plugin! ;-)






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

* Re: Negative float problem
  2005-11-02 14:20                                 ` Jean-Pierre Rosen
@ 2005-11-02 20:15                                   ` Jeffrey R. Carter
  2005-11-03 13:06                                     ` Jean-Pierre Rosen
  2005-11-03  9:51                                   ` Maciej Sobczak
  1 sibling, 1 reply; 47+ messages in thread
From: Jeffrey R. Carter @ 2005-11-02 20:15 UTC (permalink / raw)


Jean-Pierre Rosen wrote:

> Since you are new to Ada, there is something that you must understand. 
> The Ada language has been designed in such a way that either a construct 
> always works, and works the same with every implementation, or does not 
> compile. There is no space for "sometimes", "maybe", "depends", and 
> other things like that that are common in other languages.

Mostly. There are a number of "implementation defined" parts of the language. 
What's the range of type Integer? At least that of a 16-bit signed 
twos-complement integer, but often more. Luckily, you can define your own 
integer types that match your application's needs, and not have to rely on the 
predefined numeric types, as you have to do in most other languages.

SPARK gets rid of most implementation-defined things, but type Integer is still 
in there ...

-- 
Jeff Carter
"My legs are gray, my ears are gnarled, my eyes are old and bent."
Monty Python's Life of Brian
81



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

* Re: Negative float problem
  2005-11-02 14:20                                 ` Jean-Pierre Rosen
  2005-11-02 20:15                                   ` Jeffrey R. Carter
@ 2005-11-03  9:51                                   ` Maciej Sobczak
  2005-11-03 13:20                                     ` Jean-Pierre Rosen
  2005-11-03 20:59                                     ` Simon Wright
  1 sibling, 2 replies; 47+ messages in thread
From: Maciej Sobczak @ 2005-11-03  9:51 UTC (permalink / raw)


Hi,

Jean-Pierre Rosen wrote:

> Since you are new to Ada, there is something that you must understand. 
[...]
> There is no space for "sometimes", "maybe", "depends", and 
> other things like that that are common in other languages.

I understand what you wanted to say but I don't share the sentiment that 
is behind the way you worded it.

Example:

I'm writing a library subroutine and in this subroutine I raise an 
exception.
Question: can I be sure that the exception will be handled? In other 
words: can I be sure that not handling of this exception will be 
detected by the language run-time and reported as error?

Answer: *sometimes* yes, but *sometimes* no - it *depends* and *maybe* 
the exception will be quitely lost without anybody noticing it.

What's the problem in the above? The problem is that there are two 
language features - exceptions and tasking - and that they can 
*interact*. It is not trivial to come up with correct scheme for this 
interaction and if you ask two experts you will get three different 
opinions on the issue.

The same is with ADL and packages, namespaces, private/public view, etc. 
- these are things that can *interact* and you have to use some 
conditional wording in order to define this interaction. This is true 
*everywhere* where two features interact.
I'm glad that ADL triggered some discussion here, because I learned 
something in the meantime - that's my objective for lurking here, after all.
But please don't use words like "maybe" in order to make the idea look 
unserious or not Ada-worthy, or in order to make other languages look 
inferior, because it simply does not hold water.


Imagine some Ada programmer decided to learn C++. He comes to the C++ 
newsgroup, asks a couple of why this or that and I give him this answer:

"You are new to C++, so you must understand something: exceptions are 
*never* quietly lost. There is no place for "sometimes", "maybe" or 
"depends", as in other languages (that you already know). C++ will 
protect you."

Would it help him? No. (in fact, this kind of mentoring attitute can 
raise the psychological entry barrier)
Would it move anything forward? No.
Does it hold water? No.

So let's not do this.

-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-11-02 20:15                                   ` Jeffrey R. Carter
@ 2005-11-03 13:06                                     ` Jean-Pierre Rosen
  2005-11-03 18:32                                       ` Jeffrey R. Carter
  0 siblings, 1 reply; 47+ messages in thread
From: Jean-Pierre Rosen @ 2005-11-03 13:06 UTC (permalink / raw)


Jeffrey R. Carter a �crit :
> Jean-Pierre Rosen wrote:
> 
>> Since you are new to Ada, there is something that you must understand. 
>> The Ada language has been designed in such a way that either a 
>> construct always works, and works the same with every implementation, 
>> or does not compile. There is no space for "sometimes", "maybe", 
>> "depends", and other things like that that are common in other languages.
> 
> 
> Mostly. There are a number of "implementation defined" parts of the 
> language. What's the range of type Integer? At least that of a 16-bit 
> signed twos-complement integer, but often more. Luckily, you can define 
> your own integer types that match your application's needs, and not have 
> to rely on the predefined numeric types, as you have to do in most other 
> languages.
> 
> SPARK gets rid of most implementation-defined things, but type Integer 
> is still in there ...
> 
Sure, there are parts that are "implementation defined", but at least, 
you know precisely what they are. And bear in mind that "implementation 
defined" does not necessarily mean "non portable" (depends on your 
definition of "portable"). For example:

type Biggest_Int is range System.Min_Int .. System.Max_Int;

The range will vary with the implementation, but it will always be the 
biggest integer type available on your system.

-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



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

* Re: Negative float problem
  2005-11-03  9:51                                   ` Maciej Sobczak
@ 2005-11-03 13:20                                     ` Jean-Pierre Rosen
  2005-11-03 15:02                                       ` Maciej Sobczak
  2005-11-03 20:59                                     ` Simon Wright
  1 sibling, 1 reply; 47+ messages in thread
From: Jean-Pierre Rosen @ 2005-11-03 13:20 UTC (permalink / raw)


Maciej Sobczak a �crit :
>> Since you are new to Ada, there is something that you must understand. 
> 
> [...]
> 
>> There is no space for "sometimes", "maybe", "depends", and other 
>> things like that that are common in other languages.
> 
> 
> I understand what you wanted to say but I don't share the sentiment that 
> is behind the way you worded it.
> 
> Example:
> 
> I'm writing a library subroutine and in this subroutine I raise an 
> exception.
> Question: can I be sure that the exception will be handled? In other 
> words: can I be sure that not handling of this exception will be 
> detected by the language run-time and reported as error?
> 
> Answer: *sometimes* yes, but *sometimes* no - it *depends* and *maybe* 
> the exception will be quitely lost without anybody noticing it.
> 
> What's the problem in the above? The problem is that there are two 
> language features - exceptions and tasking - and that they can 
> *interact*. It is not trivial to come up with correct scheme for this 
> interaction and if you ask two experts you will get three different 
> opinions on the issue.
That's a totally different issue. Of course, what happens with an 
exception depends on which context it was raised in. However, the 
behaviour will be the same on every compiler and every machine.

[...]
> But please don't use words like "maybe" in order to make the idea look 
> unserious or not Ada-worthy, or in order to make other languages look 
> inferior, because it simply does not hold water.
The "maybe" I was refering to was about the semantic definition of the 
language. Ada does its best (but nobody's perfect) to define precisely 
the semantics of every construct.

For example, try to find what "%" does in C/C++ (with at least one 
negative operand, of course)...

> Imagine some Ada programmer decided to learn C++. He comes to the C++ 
> newsgroup, asks a couple of why this or that and I give him this answer:
> 
> "You are new to C++, so you must understand something: exceptions are 
> *never* quietly lost. There is no place for "sometimes", "maybe" or 
> "depends", as in other languages (that you already know). C++ will 
> protect you."
> 
> Would it help him? No. (in fact, this kind of mentoring attitute can 
> raise the psychological entry barrier)
> Would it move anything forward? No.
> Does it hold water? No.
> 
I'm sorry if you took my message as some unpleasant "mentoring 
attitude". What I was refering to is that Ada has been designed from a 
requirements document, and that document stipulated that the language 
had to be uniform and consistent. Sometimes it shows up in not so 
user-friendly ways, and you have to understand it in order to accept it 
as "the price to pay".
-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



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

* Re: Negative float problem
  2005-11-03 13:20                                     ` Jean-Pierre Rosen
@ 2005-11-03 15:02                                       ` Maciej Sobczak
  2005-11-03 18:55                                         ` Frank J. Lhota
  0 siblings, 1 reply; 47+ messages in thread
From: Maciej Sobczak @ 2005-11-03 15:02 UTC (permalink / raw)


Jean-Pierre Rosen wrote:

> For example, try to find what "%" does in C/C++ (with at least one 
> negative operand, of course)...

For fundamental types, this always holds (except when b is 0):

a == (a / b) * b + a % b

If any of a or b is negative, then the sign of a % b is 
implementation-defined.

(for user-defined types - like MySuperSafeIntegerWithLotsOfChecks - it's 
of course whatever you invent it to be)

I have to admit that I was never concerned with this rule, I just don't 
divide modulo negative numbers - this kind of operation simply has no 
meaning in any of the domains where I used C/C++.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-11-03 13:06                                     ` Jean-Pierre Rosen
@ 2005-11-03 18:32                                       ` Jeffrey R. Carter
  0 siblings, 0 replies; 47+ messages in thread
From: Jeffrey R. Carter @ 2005-11-03 18:32 UTC (permalink / raw)


Jean-Pierre Rosen wrote:

> type Biggest_Int is range System.Min_Int .. System.Max_Int;
> 
> The range will vary with the implementation, but it will always be the 
> biggest integer type available on your system.

Sure, I've done this on many occasions. It's fine if you want the largest range, 
without any specific values for a minimum range. I often use it to have a 'Image 
for universal integers. "digits System.Max_Digits" is good for the case of 
universal reals.

On the other hand, from another thread, we have

type A is delta B range -1.0 .. 1.0;

and what "1.0 in A" is.

-- 
Jeff Carter
"Now go away or I shall taunt you a second time."
Monty Python & the Holy Grail
07



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

* Re: Negative float problem
  2005-11-03 15:02                                       ` Maciej Sobczak
@ 2005-11-03 18:55                                         ` Frank J. Lhota
  2005-11-04  9:32                                           ` Maciej Sobczak
  0 siblings, 1 reply; 47+ messages in thread
From: Frank J. Lhota @ 2005-11-03 18:55 UTC (permalink / raw)


Maciej Sobczak wrote:
> Jean-Pierre Rosen wrote:
> 
>> For example, try to find what "%" does in C/C++ (with at least one 
>> negative operand, of course)...
> 
> 
> For fundamental types, this always holds (except when b is 0):
> 
> a == (a / b) * b + a % b
> 
> If any of a or b is negative, then the sign of a % b is 
> implementation-defined.
> 
> (for user-defined types - like MySuperSafeIntegerWithLotsOfChecks - it's 
> of course whatever you invent it to be)
> 
> I have to admit that I was never concerned with this rule, I just don't 
> divide modulo negative numbers - this kind of operation simply has no 
> meaning in any of the domains where I used C/C++.

There are applications, however, where negative integers are divided and 
remaindered. If such applications are moved to a platform where "/" and 
"%" are handled differently, portability time bombs are likely to be 
exposed.

Fortunately, this issue has been addressed by the C standards folks, and 
the C99 standard specifies that integer division must round to 0. This 
should make Ada fans happy, since the Ada standard required this since 
1983. Moreover, C99 requires that "%" behaves like "rem".

The bad news is that there are few C99 compilers, due to the rapid 
switch to C++. The C++ standard needs to be revised to address this 
issue. All of the C++ compilers I have used round to 0. Are there any 
C++ compilers in current use that do NOT round to 0?

-- 
"All things extant in this world,
Gods of Heaven, gods of Earth,
Let everything be as it should be;
Thus shall it be!"
- Magical chant from "Magical Shopping Arcade Abenobashi"

"Drizzle, Drazzle, Drozzle, Drome,
Time for the this one to come home!"
- Mr. Lizard from "Tutor Turtle"



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

* Re: Negative float problem
  2005-11-03  9:51                                   ` Maciej Sobczak
  2005-11-03 13:20                                     ` Jean-Pierre Rosen
@ 2005-11-03 20:59                                     ` Simon Wright
  1 sibling, 0 replies; 47+ messages in thread
From: Simon Wright @ 2005-11-03 20:59 UTC (permalink / raw)


Maciej Sobczak <no.spam@no.spam.com> writes:

> I'm writing a library subroutine and in this subroutine I raise an
> exception.
> Question: can I be sure that the exception will be handled? In other
> words: can I be sure that not handling of this exception will be
> detected by the language run-time and reported as error?

But this is not your problem -- it's up to the user (or the tech lead
who decides to use your library) to be sure that it's used correctly,
and that includes catching any exceptions you may raise.



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

* Re: Negative float problem
  2005-11-03 18:55                                         ` Frank J. Lhota
@ 2005-11-04  9:32                                           ` Maciej Sobczak
  0 siblings, 0 replies; 47+ messages in thread
From: Maciej Sobczak @ 2005-11-04  9:32 UTC (permalink / raw)


Frank J. Lhota wrote:

> There are applications, however, where negative integers are divided and 
> remaindered. If such applications are moved to a platform where "/" and 
> "%" are handled differently, portability time bombs are likely to be 
> exposed.

Sure - as with any other "implementation defined" element, in *every* 
language that has them.
If you are worried about the fact that the range of Integer is 
implementation-defined in Ada, don't use it and instead roll your own 
types for whatever domain you are in.
Same for % in C++.

The question what should be implementation defined in the language is a 
valid one, though. If you say that Integer'Range (and sizeof(int)) 
*should* be implementation-defined whereas rem/% should not, I will not 
object.

> Are there any 
> C++ compilers in current use that do NOT round to 0?

I have no idea. As I said - I have not seen any domain where this would 
be of any concern (and actually, you haven't named any neither ;) ).
If it was of any concern, I would certainly define my own types for this 
kind of operations. It is possible to implement them in a way that would 
map to native implementation where they are equivalent.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Negative float problem
  2005-11-02  0:28                         ` Robert A Duff
  2005-11-02  4:16                           ` Steve Whalen
@ 2005-11-14  7:26                           ` Dave Thompson
  2005-11-20  0:19                             ` Robert A Duff
  1 sibling, 1 reply; 47+ messages in thread
From: Dave Thompson @ 2005-11-14  7:26 UTC (permalink / raw)


On 01 Nov 2005 19:28:34 -0500, Robert A Duff
<bobduff@shell01.TheWorld.com> wrote:
<snip>
> Right.  That was my point: functions do not overload on their return
> type in C++.
> 
That's true.

> It's the same reason why you have to put an annoying "L" at the end of a
> "long int" literal in C++.  That's a kludge, and it wouldn't work at all
> in Ada, which has many integer types.  Have I got that right?
> 
No and no.

First, you don't always need a suffix L (or LL for long long in C99).
Literals have specific types in C and C++ (i.e. no Universal_Integer)
and a decimal literal unsuffixed has the smallest signed integer type
capable of representing it. On a system with 16-bit int, 1000000 is
long int. Where you do need it (or alternatively a cast) is:

- when passed as argument (actual) to a function declared without a
prototype (obsolete and bad style since 89 but still allowed), or as a
variable argument e.g.: printf ("%ld", 3L /* not just 3 */);

- when used in certain (arithmetic) expressions:
  1000 /* always int */ * 1000 /* ditto */
on system with 16-bit int is computed in 16 bits (not promoted) and
overflows, can't produce correct result and may go undiagnosed
  1000L * 1000 /* promoted to long, computed in long, safe */

You do more often need a suffix U (or cast) for unsigned -- but not
always; octal and hexadecimal (but not decimal) unsuffixed literals of
certain sizes are automatically unsigned. And signed ones are silently
and losslessly converted if they meet unsigned in an expression. 

You might write suffixes even where not required, for documentation.
Just as I might 'use Foo.Bar' and still write Foo.Bar.X or Bar.X
instead of just X.

Second, this still has nothing to do with overloading on return type.
A numeric literal is not a function, not even in Ada. It can be an
argument, and matching and conversion of actual arguments to formal
parameters of possible overloads in C++ is basically similar to Ada.

- David.Thompson1 at worldnet.att.net



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

* Re: Negative float problem
  2005-11-14  7:26                           ` Dave Thompson
@ 2005-11-20  0:19                             ` Robert A Duff
  2005-11-20 11:07                               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 47+ messages in thread
From: Robert A Duff @ 2005-11-20  0:19 UTC (permalink / raw)


Dave Thompson <david.thompson1@worldnet.att.net> writes:

> On 01 Nov 2005 19:28:34 -0500, Robert A Duff
> <bobduff@shell01.TheWorld.com> wrote:
> <snip>
> > Right.  That was my point: functions do not overload on their return
> > type in C++.
> > 
> That's true.
> 
> > It's the same reason why you have to put an annoying "L" at the end of a
> > "long int" literal in C++.  That's a kludge, and it wouldn't work at all
> > in Ada, which has many integer types.  Have I got that right?
> > 
> No and no.

Not sure what's "No".  Certainly it's a kludge, and certainly it
wouldn't work in Ada, since there are an unbounded number of
integer types.

> First, you don't always need a suffix L (or LL for long long in C99).

OK.  So you need it exactly when you can't tell the appropriate type of
the literal by looking at the literal itself.  E.g., in your 1000*1000
example, below -- you have to add an "L" to get the right answer.

> Literals have specific types in C and C++ (i.e. no Universal_Integer)
> and a decimal literal unsuffixed has the smallest signed integer type
> capable of representing it. On a system with 16-bit int, 1000000 is
> long int. Where you do need it (or alternatively a cast) is:
> 
> - when passed as argument (actual) to a function declared without a
> prototype (obsolete and bad style since 89 but still allowed), or as a
> variable argument e.g.: printf ("%ld", 3L /* not just 3 */);
> 
> - when used in certain (arithmetic) expressions:
>   1000 /* always int */ * 1000 /* ditto */
> on system with 16-bit int is computed in 16 bits (not promoted) and
> overflows, can't produce correct result and may go undiagnosed
>   1000L * 1000 /* promoted to long, computed in long, safe */
> 
> You do more often need a suffix U (or cast) for unsigned -- but not
> always; octal and hexadecimal (but not decimal) unsuffixed literals of
> certain sizes are automatically unsigned. And signed ones are silently
> and losslessly converted if they meet unsigned in an expression. 
> 
> You might write suffixes even where not required, for documentation.
> Just as I might 'use Foo.Bar' and still write Foo.Bar.X or Bar.X
> instead of just X.

Yes.  Perhaps a better analogy would be saying "My_Integer'(X)" instead
of just "X".

> Second, this still has nothing to do with overloading on return type.

It has a lot to do with overloading on return type.  The point is
whether overload resolution uses context to determine the type of an
expression result -- that could be the result of a function call, the
result of a literal, or various other things, depending on the
language.

> A numeric literal is not a function, not even in Ada. 

It doesn't matter that literals are not functions.  As far as the design
of overload resolution goes, they are analogous.

>...It can be an
> argument, and matching and conversion of actual arguments to formal
> parameters of possible overloads in C++ is basically similar to Ada.

No, C++ and Ada are completely different in this regard: In C++, the
literal itself determines its type (the value, plus the presence of
"L"), as you explained above.  In Ada, the _context_ determines the type
of the literal.  This is analogous to the function-call case:
In C++, the innards of the function call determine which function is
called, and therefore, its type.  In Ada, the context is used
(in addition to the innards).

Example:

    function F return Integer;
    function F return Boolean;
    procedure P(X: Integer);

    P(F*F); -- (1)

    type Int is range -2**15 .. 2**15-1;
    type Long is range -2**31 .. 2**31-1;
    procedure Q(X: Long);

    Q(1000*1000); -- (2)

In Ada, the F's at (1) are the Integer one, and the 1000's at (2) are of
type Long.  If we translate to C++, I believe (1) is a compile-time
error, and (2) gets the wrong answer.

- Bob



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

* Re: Negative float problem
  2005-11-20  0:19                             ` Robert A Duff
@ 2005-11-20 11:07                               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 47+ messages in thread
From: Dmitry A. Kazakov @ 2005-11-20 11:07 UTC (permalink / raw)


On 19 Nov 2005 19:19:32 -0500, Robert A Duff wrote:

> No, C++ and Ada are completely different in this regard: In C++, the
> literal itself determines its type (the value, plus the presence of
> "L"), as you explained above.  In Ada, the _context_ determines the type
> of the literal.

Right. There could be two different ways to describe what's going on. One
is to say that all literals overload each other (as if they were
functions.) Another is to create a common ancestor type for homographs and
overload conversions from them (Universal_Integer, is an example.) Ada uses
both and both require the context.

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



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

end of thread, other threads:[~2005-11-20 11:07 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-26 18:32 Negative float problem Luke
2005-10-26 19:05 ` Samuel Tardieu
2005-10-26 20:42 ` Robert A Duff
2005-10-27  8:05   ` Robert I. Eachus
2005-10-27 14:48     ` Robert A Duff
2005-10-27 15:07       ` Maciej Sobczak
2005-10-27 15:47         ` Robert A Duff
2005-10-28  8:34           ` Maciej Sobczak
2005-10-29 23:39             ` Brian May
2005-10-30  9:11             ` Dmitry A. Kazakov
2005-10-31  9:46               ` Maciej Sobczak
2005-10-31 14:20                 ` Dmitry A. Kazakov
2005-11-01 11:06                   ` Maciej Sobczak
2005-11-01 14:06                     ` Robert A Duff
2005-11-01 14:46                       ` Martin Dowie
2005-11-01 16:04                         ` Hyman Rosen
2005-11-01 17:19                           ` Martin Dowie
2005-11-02  0:13                         ` Robert A Duff
2005-11-02  6:59                           ` Martin Dowie
2005-11-02 13:24                             ` Robert A Duff
2005-11-02 15:22                               ` Martin Dowie
2005-11-01 15:12                       ` Maciej Sobczak
2005-11-02  0:28                         ` Robert A Duff
2005-11-02  4:16                           ` Steve Whalen
2005-11-14  7:26                           ` Dave Thompson
2005-11-20  0:19                             ` Robert A Duff
2005-11-20 11:07                               ` Dmitry A. Kazakov
2005-11-01 14:27                     ` Dmitry A. Kazakov
2005-11-01 15:19                       ` Maciej Sobczak
2005-11-01 19:44                         ` Dmitry A. Kazakov
2005-11-02  9:04                           ` Maciej Sobczak
2005-11-02 11:17                             ` Dmitry A. Kazakov
2005-11-02 13:03                               ` Maciej Sobczak
2005-11-02 14:20                                 ` Jean-Pierre Rosen
2005-11-02 20:15                                   ` Jeffrey R. Carter
2005-11-03 13:06                                     ` Jean-Pierre Rosen
2005-11-03 18:32                                       ` Jeffrey R. Carter
2005-11-03  9:51                                   ` Maciej Sobczak
2005-11-03 13:20                                     ` Jean-Pierre Rosen
2005-11-03 15:02                                       ` Maciej Sobczak
2005-11-03 18:55                                         ` Frank J. Lhota
2005-11-04  9:32                                           ` Maciej Sobczak
2005-11-03 20:59                                     ` Simon Wright
2005-11-02 13:32                               ` Robert A Duff
2005-11-02 14:44                                 ` Dmitry A. Kazakov
2005-11-02 13:47                               ` Dmitry A. Kazakov
2005-10-27 18:33       ` Dmitry A. Kazakov

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