[comp.lang.ada] Unusual "use" semantics

fred@polymnia.tsd.arlut.utexas.edu (Fred Hosch) (08/09/90)

My Ada compiler complains about the relation on the fourth line of the
following

	with TEXT_IO;
	procedure TEST is
	begin
	    if TEXT_IO.COL = 1 then
	        TEXT_IO.PUT_LINE ("COL is 1");
	    else
	        TEXT_IO.PUT_LINE ("COL is not 1");
	    end if;
	end TEST;

reporting: no operator visible for positive_count "=" universal integer.

If I add a context clause "use TEXT_IO;" it compiles successfully.

Is this a compiler bug or am I missing something in the LRM?

	Fred Hosch
	Applied Research Labs
	UT Austin
	fred@cs.utexas.edu
	fred@titan.tsd.arlut.utexas.edu

jm21@prism.gatech.EDU (Jim Marks) (08/09/90)

In article <20@polymnia.tsd.arlut.utexas.edu> fred@polymnia.tsd.arlut.utexas.edu (Fred Hosch) writes:
>My Ada compiler complains about the relation on the fourth line of the
>following
>
>	with TEXT_IO;
>	procedure TEST is
>	begin
>	    if TEXT_IO.COL = 1 then
>...
>
>reporting: no operator visible for positive_count "=" universal integer.
>
>If I add a context clause "use TEXT_IO;" it compiles successfully.
>

This is a result of the strong typing and operator overloading of Ada.  
The "=" operator you have visible can take two integer type arguments.  
However, the return value of TEXT_IO.COL is of type POSITIVE_COUNT, which 
is a subtype of type COUNT, declared in the Text_IO package (LRM 14.3.10).  
This type has its own "=" operator implicitly declared for it in Text_IO.
When you include the "use" clause for Text_IO, then the "=" operator for 
this type (COUNT) is then visible (in this case, the "1" is considered 
of this type so that it matches).  You could also do the following:

if integer(Text_IO.Col) = 1 then ...   which converts the return value
				to integer, OR

if Text_IO."=" ( Text_IO.Col , 1 ) then ...   which is UGLY.

I've had this problem many times when I don't think about it in advance.
This is a good application of the "use" clause, even though some coding
standards discourage (or prohibit) the use of "use" clauses.

-- 
Jim Marks   		   | Georgia Tech Research Institute
Compuserve: 72310,2410     | Concepts Analysis Laboratory
Internet:   jm21@prism.gatech.edu -or- jmarks@gtri01.gatech.edu

palo@rikka.enet.dec.com (Rik Palo) (08/09/90)

Function TEXT_IO.COL returns POSITIVE_COUNT, which is a subtype of
TEXT_IO.COUNT.  Since
the type definition for COUNT is declared in TEXT_IO, its default operations
(such as  '=') are implicitly declared there as well.  Either a 'use' clause or
a function renames would make the operator visible (for more on function
renames, see LRM 8.5).

	good luck

		-- Rik Palo
	

mwever@encore (Mike Wever) (08/09/90)

i would disagree that "good programing practice prohibits the use of the "use"
use clause". it it my understanding that the use clause was put in for infix
operator such as "=". i would submit to this group that the addition of the use 
clause to avoid the ugly case is indeed much cleaner code then without. the
abuse of the use clause has more to do with using it to avoid dotted notions
for objects, functions, procedures, and or types with are visable from the
specs of "withed" packages.

i spent a year or so looking at a 300K loc system which was written in ada. it
was very hard to understand because of the fact that the use clause was used 
to avoid dotted notions. my humble advice is then to only use the use clause to
make directly visable an infix operator, and make all other items expressly
clear by using dotted notation. when i am changing a piece of code i often
comment out the use clause and put in the dotted notions, and only put it back
in if there is an infix operator which should be directly visable.

adoyle@bbn.com (Allan Doyle) (08/09/90)

In article <20@polymnia.tsd.arlut.utexas.edu> fred@polymnia.tsd.arlut.utexas.edu (Fred Hosch) writes:
>My Ada compiler complains about the relation on the fourth line of the
>following
>
>	with TEXT_IO;
>	procedure TEST is
>	begin
>	    if TEXT_IO.COL = 1 then
>	        TEXT_IO.PUT_LINE ("COL is 1");
>	    else
>	        TEXT_IO.PUT_LINE ("COL is not 1");
>	    end if;
>	end TEST;
>
>reporting: no operator visible for positive_count "=" universal integer.
>
>If I add a context clause "use TEXT_IO;" it compiles successfully.
>

The way we have chosen to avoid use and to avoid the ugliness
of TEXT_IO."=" is by using renames:

	function "="(l:text_io.count;r:integer) return boolean
		renames text_io."=";

Sometimes this can get out of hand, with a ton of renames at the top
of packages or procedures but it does make it clear without cluttering
up the logic once you're into the code body.




Allan Doyle                                        adoyle@bbn.com
BBN Systems and Technologies Corporation           (617) 873-3398
70 Fawcett Street,   Cambridge, MA 02138

pattis@cs.washington.edu (Richard Pattis) (08/09/90)

In article <12435@encore.Encore.COM>, mwever@encore (Mike Wever) writes:
> i would disagree that "good programing practice prohibits the use of the
> "use" use clause". it it my understanding that the use clause was put in
> for infix operator such as "=". i would submit to this group that the
> addition of the use clause to avoid the ugly case is indeed much cleaner
> code then without. the abuse of the use clause has more to do with using it
> to avoid dotted notions for objects, functions, procedures, and or types
> with are visable from the specs of "withed" packages.
> 
> i spent a year or so looking at a 300K loc system which was written in ada.
> it was very hard to understand because of the fact that the use clause was
> used to avoid dotted notions. my humble advice is then to only use the use
> clause to make directly visable an infix operator, and make all other items
> expressly clear by using dotted notation. when i am changing a piece of
> code i often comment out the use clause and put in the dotted notions, and
> only put it back in if there is an infix operator which should be directly
> visable.

(1) We can also overload "=" by

  FUNCTION "=" (L : POSITIVE_COUNT; R : INTEGER) RETURN BOOLEAN
    RENAMES TEXTIO."=";

So we can use this mechanism selectively, to make some subprograms visible
without using USE to make all entities in a package visible.

(2) When we construct a package that overloads lots of infix operators (say a
complex number package) we can place all the operators inside a nested
package, and then USE only that nested package (not the outer one).
This allows infix notation for all the operators in the nested package, while
forcing selected names for all the other entities declared in the package.

I came on this idea (no doubt invented many times before) to solve exactly
the problem stated above, in a CS-1 book chapter I'm writing.  This was my
only example of nested packages. Does anyone have any other good examples of
nested packges that I could use in my book?

Rich Pattis

kolender@ics.uci.edu (Kurt Olender) (08/09/90)

Fred Hosch writes:

   My Ada compiler complains about the relation on the fourth line of the
   following

	   with TEXT_IO;
	   procedure TEST is
	   begin
	       if TEXT_IO.COL = 1 then
		   TEXT_IO.PUT_LINE ("COL is 1");
	       else
		   TEXT_IO.PUT_LINE ("COL is not 1");
	       end if;
	   end TEST;

   reporting: no operator visible for positive_count "=" universal integer.

There is one other solution that hasn't been put forward that avoids both the
"ugliness" of calling text_io."="(...) and the "use" clause, a rename
statement, as follows:

     function "=" (a, b: text_io.positive_count)
	      return boolean
	      renames text_io."=";


You may then write

    if (text_io.col = 1) ...

and the compiler will have a visible comparison operator for positive count.

I prefer this method, even though it involves more typing, because it
explicitly makes visible only those things you really need to be visible, and
reduces the potential name clashes that "use" can cause.

kaplan@pogo.cs.umass.edu (Alan Kaplan) (08/11/90)

ANother solution is to specify the "use clause" within the scope of a
procedure or function.  This makes all names visible from the "use'd"
package within this scope.
--

                             Regards,

                             Alan 

                             kaplan@cs.umass.edu